Golang是否将nil作为可选参数传递给函数?

Golang是否将nil作为可选参数传递给函数?,go,Go,在Golang中,http.NewRequest有如下规范: func NewRequest(method, urlStr string, body io.Reader) (*Request, error) req, err := http.NewRequest("GET", "http://www.blahblah.org", nil) func getChallenges(after string) ([]challenge, string, error) 但是,如果我不想将body传

在Golang中,
http.NewRequest
有如下规范:

func NewRequest(method, urlStr string, body io.Reader) (*Request, error)
req, err := http.NewRequest("GET", "http://www.blahblah.org", nil)
func getChallenges(after string) ([]challenge, string, error)
但是,如果我不想将
body
传递给
io.Reader
对象,我可以将
nil
作为
body
选项传递,如下所示:

func NewRequest(method, urlStr string, body io.Reader) (*Request, error)
req, err := http.NewRequest("GET", "http://www.blahblah.org", nil)
func getChallenges(after string) ([]challenge, string, error)
如何在代码中实现此功能?我有一个函数,我想传递一个可选的字符串值,以便它可以通过API结果进行分页,但是如果我将
nil
传递给字符串输入,我会得到以下结果:

./snippets.go:32:无法将nil转换为字符串类型

my函数的参数如下所示:

func NewRequest(method, urlStr string, body io.Reader) (*Request, error)
req, err := http.NewRequest("GET", "http://www.blahblah.org", nil)
func getChallenges(after string) ([]challenge, string, error)
Go在其他语言中没有“可选”参数作为一个普遍理解的概念
nil
只是接口的零值(
io.Reader

字符串的等效零值为空字符串:

getChallenges("")
如果要接受0或更多相同参数类型,请使用可变语法:

func getChallenges(after ...string) ([]challenge, string, error)
您可以使用reflect。 实际上,
io.Reader
是一个接口

因此,您可以定义签名,如
func-getChallenges(在接口{}之后)([]质询,字符串,错误)

接口{}是一个空接口,即任何对象的接口

但是我建议您使用语法
args…
来传递slice,请参阅
fmt.Printf
实现以了解用法,因为如果您不传递字符串,slice len为0和
这将避免反射,我认为反射对您的功能来说太重。

您可以使用椭圆运算符发送可选参数。。不要在可选参数中传递任何内容,并检查参数的长度。 它应该能解决你的问题

func foo(params ...int) {
   fmt.Println(len(params))
}

func main() {
    foo()
    foo(1)
    foo(1,2,3)
}

您可以修改函数以接收指针值,如下所示:

func NewRequest(method, urlStr string, body io.Reader) (*Request, error)
req, err := http.NewRequest("GET", "http://www.blahblah.org", nil)
func getChallenges(after string) ([]challenge, string, error)
func-getChallenges(在*string之后)([]质询,字符串,错误)

然后可以将
nil
作为参数传递给它。但是,在取消引用函数之前,不要忘记在函数中检查
之后的
是否有
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 */)
}

也许把它包装在一个
结构中

类型NilableString结构{
值字符串;
}

我使用的是空字符串“”,不过我要实现可变语法。我假设这类似于python中的*arg/**kwargs。干杯Go确实有可选参数,带有variadics。@MikeSchinkel:variadics是variadics,我在答案中指出它们是一种可能的解决方案。因为go语言规范没有定义“可选参数”,所以您需要借用其他语言的定义,比如python或ruby,这些是不同的概念,因为它们也有可变参数,这一点更加明显。在定义和描述编程概念时,使用的语言的精确性是非常重要的。我非常同意使用精确的语言是重要的,这就是我评论的原因。您的语句“Go中的任何参数都是“可选的”;“可能会被错误读取。如果不传递命名参数,则无法调用函数。”。如果你说“Go没有其他语言中普遍理解的“可选”参数”,那么我就不会发表评论了。或者,如果您以“Go中没有参数是“可选的”,但Go确实有变量”开头,我也不会发表评论,因为您在结尾提到变量会受到常见的
#tldr网络上的问题。@MikeSchinkel:关于第一行的语义,这是一个足够公平的评论,可能只是在文章中作为编辑提交的(毕竟这是公认的做法)。将参数设置为*字符串的一个巨大缺点是,您不能获取字符串文本的地址,它也不会自动为您装箱字符串。“just add another function”参数可能导致处理多个排列所需的方法激增,需要为这些方法确定有意义、可发现和可记忆的名称,并增加学习使用更多方法而不是更少方法的包的负担#jmtcw