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

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?

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
", canBeString.String());
 } else {
  fmt.Print("Nothing to say !
");
 }
}

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

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

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

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.

I know I'm super late to this party, but I found this while searching for a similar issue, and thought I'd add my solution for posterity.

Depending on your use case, using a variadic function may be your friend. This lets you enter zero or more arguments of the same type to a function, which are received within the function as an array.

// 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!

This solution does require that you know you're going to be passing in a nil at development time; you can't just call f(nil) and have it work. But, if this isn't a problem in your particular use case, it could be a very elegant solution that doesn't require you to define any additional data types.