Golang如何将nil作为可选参数传递给函数?

huangapple go评论155阅读模式
英文:

Golang pass nil as optional argument to a function?

问题

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

func NewRequest(method, urlStr string, body io.Reader) (*Request, error)

然而,如果我不想将body传递给io.Reader对象,我可以将nil作为body选项传递,像这样:

req, err := http.NewRequest("GET", "http://www.blahblah.org", nil)

我该如何在我的代码中实现这个功能?我有一个函数,我想传递一个可选的字符串值,以便它可以通过API结果进行分页,但是如果我将nil传递给字符串输入,我会得到以下错误:

./snippets.go:32: cannot convert nil to type string

我的函数参数如下所示:

func getChallenges(after string) ([]challenge, string, error)

请注意,这只是一个翻译,我不会回答关于代码实现的问题。

英文:

In Golang, http.NewRequest has a specification like this:

func NewRequest(method, urlStr string, body io.Reader) (*Request, error)

However, I can pass nil as the body option if I don't want to pass the body to an io.Reader object, like this:

req, err := http.NewRequest("GET", "http://www.blahblah.org", nil)

How do I implement this functionality in my code? I have a function that I want to pass an optional string value so that it can page through API results however if I pass a nil to the string input I get this:

>./snippets.go:32: cannot convert nil to type string

The parameters for my function look like this:

func getChallenges(after string) ([]challenge, string, error)

答案1

得分: 14

Go语言中没有“可选”参数的概念,这在其他语言中通常是可以理解的;nil只是接口类型(在这种情况下是io.Reader)的零值。

字符串的零值是空字符串:

getChallenges("")

如果你想接受0个或多个相同类型的参数,可以使用可变参数语法:

func getChallenges(after ...string) ([]challenge, string, error)
英文:

Go does not have "optional" arguments as a generally understood concept in other languages; nil is just the zero value for an interface (io.Reader in this case).

The equivalent zero value for a string is an empty string:

getChallenges("")

If you want to accept 0 or more of the same argument type, you use the variadic syntax:

func getChallenges(after ...string) ([]challenge, string, error)

答案2

得分: 11

你可以修改你的函数来接收指针值,像这样:

func getChallenges(after *string) ([]challenge, string, error)

然后你可以将nil作为参数传递给它。但在解引用之前,不要忘记在函数内部检查after是否为nil值,否则会出现空指针异常:

func getChallenges(after *string) ([]challenge, string, error) {
    if after == nil {
        // 未指定值
    } else {
        fmt.Printf("After: %s\n", *after) // 注意使用"*"进行指针解引用
    }
    // ...
}

另一种选择:

只需使用两个函数:

func getChallenges(after string) {}

func getAllChallenges() {
    return getChallenges(/* 这里填写一些默认值 */)
}
英文:

You can modify you function to receive pointer value, like this:

func getChallenges(after *string) ([]challenge, string, error)

Then you can pass nil as an argument to it. But don't forget to check after for nil value inside your function before dereferencing it, or you will get a nil pointer exception:

func getChallenges(after *string) ([]challenge, string, error) {
    if after == nil {
        // No value specified
    } else {
        fmt.Printf("After: %s\n", *after) // Note pointer dereferencing with "*"
    }
    // ...
}

Another option:

Just use two functions:

func getChallenges(after string) {}

func getAllChallenges() {
    return getChallenges(/* some default value here */)
}

答案3

得分: 4

你可以使用省略号运算符来传递可选参数... 在可选参数中不传递任何内容,并检查参数的长度。
这样应该可以解决你的问题。

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

func main() {
    foo()
    foo(1)
    foo(1,2,3)
}
英文:

you can use ellipse operator to send the optional parameters.. don't pass anything in optional parameter and check the length of parameter.
it should solve your problem

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

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

答案4

得分: 0

也许可以将它包装在一个 struct 中?

type NilableString struct {
    value string;
}
英文:

Maybe wrap it in a struct?

type NilableString struct {
    value string;
}

答案5

得分: 0

以下是翻译好的内容:

这里是这样的函数如何接受nil以及值。

req, err := http.NewRequest(method, path, reader)

reader应该接受io.Readernil

package io

type Reader struct {
  ......
}

func (r Reader) getData() []byte {
  ......
}

type ReaderInterface interface {
  getData() []byte
}
package http

import "io"

func NewRequest(method string, path string, reader ReaderInterface) {
  if (reader != nil) {
    data := reader.getData()
  }
  ......
}

请注意,NewRequest期望的类型是ReaderInterface而不是Reader本身。任何具有类似上述的getData函数的类型或nil都将被接受。在内部,您可以检查reader是否不为nil。

英文:

Here is how such functions accept nil as well as value.

req, err := http.NewRequest(method, path, reader)

reader should accept io.Reader or nil

packege io

type Reader struct {
  .....
}

func (r Reader) getData() []byte {
  ......
}

type ReaderInterface interface {
  getDate() []byte
}
package http

import "io"

func NewRequest(method string, path string, reader ReaderInterface) {
  if (reader != nil) {
    data := reader.getData()
  }
  .....
}

Note that NewRequest expecting type ReaderInterface but not Reader itself. Any type with GetData function like above or nil will be accepted. Inside you can check if reader is not nil.

答案6

得分: -1

你可以使用反射(reflect)。
实际上,io.Reader 是一个接口(interface)。

所以你可以定义一个签名,像这样:func getChallenges(after interface{}) ([]challenge, string, error)

interface{} 是一个空接口,可以表示任何类型。

但是我建议你使用语法 args... 来传递切片(slice),可以参考 fmt.Printf 的实现方式,因为如果你不传递字符串,切片的长度将为0,
这样可以避免使用反射,因为我认为反射对于你的函数来说太重了。

英文:

You can use reflect.
In fact io.Reader is a interface.

So you can define signature like func getChallenges(after interface{}) ([]challenge, string, error)

interface{} is a empty interface, that is interface for anything.

But I suggest you use syntax args... to pass slice , refer to fmt.Printf implementation for usage, because if you pass no string the slice len is 0 and
this will avoid the reflect which I think too heavy for your function.

huangapple
  • 本文由 发表于 2015年9月14日 23:54:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/32568977.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定