如何在Go中使用可空字符串参数的函数?

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

How to have a function with a nullable string parameter in Go?

问题

我习惯于Java的String,我们可以传递null而不是""来表示特殊含义,比如使用默认值。

在Go中,string是一种原始类型,所以我不能将nil(null)传递给需要string类型参数的函数。

我可以使用指针类型来编写函数,像这样:

func f(s *string)

这样调用者可以这样调用该函数:

f(nil)

或者

// 不太优雅
temp := "hello";
f(&temp) 

但是以下方式不被允许:

// 优雅但不被允许
f(&"hello");

有什么最好的方法可以接收string或者nil作为参数?

英文:

I'm used to Java's String where we can pass null rather than "" for special meanings, such as use a default value.

In Go, string is a primitive type, so I cannot pass nil (null) to a parameter that requires a string.

I could write the function using pointer type, like this:

func f(s *string)

so caller can call that function either as

f(nil)

or

// not so elegant
temp := "hello";
f(&temp) 

but the following is unfortunately not allowed:

// elegant but disallowed
f(&"hello");

What is the best way to have a parameter that receives either a string or nil?

答案1

得分: 5

警告:以下是Go1之前的代码。也就是说,它来自一个预发布版本,不是有效的Go代码。

我再考虑了一下如何使用struct来实现这个。这是我想出来的:

type MyString struct {
    val string;
}

func f(s MyString) {
    if s == nil {
        s = MyString{"一些默认值"};
    }
    //对s.val进行操作
}

然后你可以这样调用f

f(nil);
f(MyString{"不是默认值"});
英文:

Warning: the following is pre-Go1 code. That is, it's from a pre-release version and is not valid Go code.

I thought some more about how I would implement this using a struct. Here's what I came up with:

type MyString struct {
    val string;
}

func f(s MyString) {
    if s == nil {
        s = MyString{"some default"};
    }
    //do something with s.val
}

Then you can call f like this:

f(nil);
f(MyString{"not a default"});

答案2

得分: 3

如果您需要处理可能的空值(例如,因为您正在与可能提供它们的数据库交互),database/sql 包提供了诸如 sql.NullStringsql.NullInt64 等类型,它们允许您使用它们的 .Valid 字段测试是否提供了值。

英文:

If you need to handle a possibble null value (becasue you are talking to a database that may provide them for example) the database/sql package has types such as sql.NullString and sql.NullInt64 that allow you to test if you have been provided with a value or not using their .Valid field.

答案3

得分: 1

不真正参与回答:但是在结构中包装值可以提供一些通用的实用方法。 (Haskell Maybe?)

//#maybe.go
package maybe

import "log"

type MayHaveValue struct {
    IsValue bool;
}

func (this MayHaveValue) IsJust() bool {
    return this.IsValue
}

type AString struct {
    MayHaveValue;
    Value string;
}

func String(aString string) AString {
    return AString{MayHaveValue{true}, aString}
}

var NoString AString = AString{MayHaveValue{false}, ""}

func (this AString) String() (value string) {
    if this.IsJust() == true {
        value = this.Value;
    } else {
        log.Crash("访问不存在的maybeString值");
    }
    return;
}

func (this AString) OrDefault(defaultString string) (value string) {
    if this.IsJust() {
        value = this.Value;
    } else {
        value = defaultString;
    }
    return;
}

//#main.go
package main

import "fmt"
import "maybe"

func say(canBeString maybe.AString) {
    if canBeString.IsJust() {
        fmt.Printf("说:%v\n", canBeString.String());
    } else {
        fmt.Print("没什么可说的!\n");
    }
}

func sayMaybeNothing(canBeString maybe.AString) {
    fmt.Printf("说:%v\n", canBeString.OrDefault("nothing"));
}

func main() {
    aString := maybe.String("你好");
    say(aString);
    sayMaybeNothing(aString);
    noString := maybe.NoString;
    say(noString);
    sayMaybeNothing(noString);
}
英文:

Not realy attend answer : but warping value in a structure can provide some generic utility methode. (Haskell Maybe ?)

//#maybe.go
package maybe

import "log"

type MayHaveValue struct {
 IsValue bool;
}

func (this MayHaveValue) IsJust() bool {
 return this.IsValue
}

type AString struct {
 MayHaveValue;
 Value string;
}

func String(aString string) AString {
 return AString{MayHaveValue{true}, aString}
}

var NoString AString = AString{MayHaveValue{false}, ""}

func (this AString) String() (value string) {
 if this.IsJust() == true {
  value = this.Value;
 } else {
  log.Crash("Access to non existent maybeString value");
 }
 return;
}

func (this AString) OrDefault(defaultString string) (value string) {
 if this.IsJust() {
  value = this.Value;
 } else {
  value = defaultString;
 }
 return;
}

//#main.go
package main

import "fmt"
import "maybe"

func say(canBeString maybe.AString) {
 if canBeString.IsJust() {
  fmt.Printf("Say : %v\n", canBeString.String());
 } else {
  fmt.Print("Nothing to say !\n");
 }
}

func sayMaybeNothing (canBeString maybe.AString) {
 fmt.Printf("Say : %v\n", canBeString.OrDefault("nothing"));
}

func main() {
 aString := maybe.String("hello");
 say(aString);
 sayMaybeNothing(aString);
 noString := maybe.NoString;
 say(noString);
 sayMaybeNothing(noString);
}

答案4

得分: 1

你可以声明一个接口来限制类型为string,并且由于接口也接受nil,所以你可以覆盖两种情况。以下是实现的方式:

type (
    // 一个接受字符串或nil值的接口。
    //
    // 你可以传递StrVal("text")或nil。
    StrOrNil interface{ isStrOrNil() }

    StrVal string // StrOrNil接口的字符串值。
)

func (StrVal) isStrOrNil() {} // 实现接口

以下是如何使用它:

func Foo(name StrOrNil) {
    switch nameVal := name.(type) {
    case StrVal:
        fmt.Printf("字符串值!%s\n", string(nameVal))
    default:
        fmt.Println("空值!")
    }
}

func main() {
    Foo(StrVal("hello world"))
    Foo(nil)
}

playground中测试它。

英文:

You can declare an interface to restrict the type to string, and since interfaces also accept nil, you'd have both cases covered. This is how you can implement it:

type (
    // An interface which accepts a string or a nil value.
    //
    // You can pass StrVal("text") or nil.
    StrOrNil interface{ isStrOrNil() }

    StrVal string // A string value for StrOrNil interface.
)

func (StrVal) isStrOrNil() {} // implement the interface

And this is how you use it:

func Foo(name StrOrNil) {
    switch nameVal := name.(type) {
    case StrVal:
        fmt.Printf("String value! %s\n", string(nameVal))
    default:
        fmt.Println("Null value!")
    }
}

func main() {
    Foo(StrVal("hello world"))
    Foo(nil)
}

Test it in the playground.

答案5

得分: -3

放弃Java思维,只需传递f("")。然后使用len()进行测试:

func f(str string) {
if len(str) > 0 {
...
} else {
...
}
}

字符串要么为空且具有nil情况的语义含义,要么具有一些字符串数据需要处理。看不出有什么问题。

英文:

Loose the Java-think and just pass f(""). Then test using len():

func f(str string) {
if len(str) > 0 {
...
} else {
...
}
}

Either the string is empty and has semantic meaning of you nil case, or else has some string data to process. Can't see the problem with that.

huangapple
  • 本文由 发表于 2009年11月26日 03:24:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/1799374.html
匿名

发表评论

匿名网友

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

确定