Golang pass nil как необязательный аргумент функции?
В Golang http.NewRequest
имеет следующую спецификацию:
func NewRequest(method, urlStr string, body io.Reader) (*Request, error)
Однако я могу передать nil
в качестве опции body
, если я не хочу передавать body
объекту io.Reader
, например так:
req, err := http.NewRequest("GET", "http://www.blahblah.org", nil)
Как мне реализовать эту функцию в моем коде? У меня есть функция, которую я хочу передать необязательное строковое значение, чтобы оно могло перелистывать результаты API, однако, если я передаю nil
в строковый ввод, я получаю это:
. /snippets.go:32: невозможно преобразовать ноль в строку типа
Параметры для моей функции выглядят так:
func getChallenges(after string) ([]challenge, string, error)
Ответы
Ответ 1
Go не имеет "необязательных" аргументов в качестве общепринятой концепции в других языках; nil
- это просто нулевое значение для интерфейса (в данном случае io.Reader
).
Эквивалентное нулевое значение для строки является пустой строкой:
getChallenges("")
Если вы хотите принять 0 или более аргументов одного и того же типа аргумента, используйте синтаксис variadic:
func getChallenges(after ...string) ([]challenge, string, error)
Ответ 2
Вы можете изменить свою функцию для получения значения указателя, например:
func getChallenges(after *string) ([]challenge, string, error)
Затем вы можете передать nil
в качестве аргумента. Но не забудьте проверить значение after
для nil
внутри вашей функции до разыменования, или вы получите исключение nil-указателя:
func getChallenges(after *string) ([]challenge, string, error) {
if after == nil {
// No value specified
} else {
fmt.Printf("After: %s\n", *after) // Note pointer dereferencing with "*"
}
// ...
}
Другая опция:
Просто используйте две функции:
func getChallenges(after string) {}
func getAllChallenges() {
return getChallenges(/* some default value here */)
}
Ответ 3
вы можете использовать оператор эллипса для отправки необязательных параметров. Не пропускайте ничего в необязательном параметре и не проверяйте длину параметра.
он должен решить вашу проблему
func foo(params ...int) {
fmt.Println(len(params))
}
func main() {
foo()
foo(1)
foo(1,2,3)
}
Ответ 4
Вы можете использовать отражение.
Фактически io.Reader
является интерфейсом.
Итак, вы можете определить подпись типа func getChallenges(after interface{}) ([]challenge, string, error)
interface {} - пустой интерфейс, который является интерфейсом для чего-либо.
Но я предлагаю вам использовать синтаксис args...
для передачи фрагмента, см. реализацию fmt.Printf
для использования, потому что если вы не передаете нить, то срез len равен 0 и
это позволит избежать отражения, которое я считаю слишком тяжелым для вашей функции.