繁体   English   中英

如何在 Go 中有一个带有可为空字符串参数的 function?

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

我习惯了 Java 的字符串,我们可以在其中传递 null 而不是 "" 以获得特殊含义,例如使用默认值

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

我可以使用指针类型编写 function,如下所示:

func f(s *string)

所以来电者可以将 function 称为

f(nil)

或者

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

但不幸的是,以下内容是不允许的:

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

让参数接收字符串或 nil 的最佳方法是什么?

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

我想了更多关于如何使用struct实现这一点的想法。 这是我想出的:

type MyString struct {
    val string;
}

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

然后你可以像这样调用f

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

我知道我参加这个派对已经太晚了,但我在寻找类似的问题时发现了这个问题,并且认为我会为后代添加我的解决方案。

根据您的使用情况,使用可变参数函数可能是您的朋友。 这允许您向函数输入零个或多个相同类型的参数,这些参数在函数内作为数组接收。

// My variadic function
func f(s string...) {
  if length(s) == 0 {
    // We got a NULL
    fmt.Println("default value")
  } else {
    // We got a value
    fmt.Println(s[0])
  }
}

f() // works!
f("has a value") // works!

这个解决方案确实要求你知道在开发时你将会以零开始; 你不能只调用f(nil)并让它工作。 但是,如果这在您的特定用例中不是问题,那么它可能是一个非常优雅的解决方案,不需要您定义任何其他数据类型。

不是真的参加答案:但是结构中的扭曲值可以提供一些通用的实用方法。 哈斯克尔也许?)

//#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);
}

如果您需要处理可能的空值(例如,因为您正在与可能提供它们的数据库交谈),则database/sql包具有诸如sql.NullStringsql.NullInt64类的类型,可让您测试是否已提供有值或不使用他们的.Valid字段。

您可以声明一个接口以将类型限制为string ,并且由于接口也接受nil ,因此您可以涵盖这两种情况。 这是你可以如何实现它:

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

这就是你如何使用它:

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)
}

操场上测试它。

放松 Java 思维,只需通过 f("")。 然后使用 len() 进行测试:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM