0

My goal is to create a function that can return nil or string value.

I use *string to allow a function to return nil or string pointer.

The problem is that function return memory address instead of the string value. The easy solution is to use *.

However, I believe that is a bad practice. E.g I am comparing it with func os.Open(name string) (*os.File, error) which return os.File pointer, but I can access the variable without *.

The best practice:

func main() {
  f, _ := os.Open("/tmp/dat")

  b1 := make([]byte, 5)
  f.Read(b1) // I don't need to use *
  fmt.Println("%s", string(b1))
}

My current code which I believe is not a best practice:

func main() {
  dat, _ := ConvertPath("/tmp/dat2")
  fmt.Println(*dat) // I need to use *
}

This is the rest of the code:

func Convert(r io.Reader) (*string, error) {
    dat := "hello"
    return &dat, nil
}

func ConvertPath(path string) (*string, error) {
    f, err := os.Open(path)
    if err != nil {
        return nil, err
    }

    defer f.Close()

    return Convert(f)
}
10
  • 2
    Return empty string in case of error. That is the idiomatic way in Go. See example. Returning pointers to strings is definitely unusual, but in cases where you truly need nil or "string", the approach you chose is acceptable. Trying to implement some "optional" type would be unidiomatic. Commented Aug 20, 2022 at 16:58
  • @mkopriva most of error check use if err != nil { // do something }. isn't empty string is not nil, hence will cause panic?. Anyway, that's not the point of this question, I want to know how os.Open can return *os.File but I can call it without *. Commented Aug 20, 2022 at 17:00
  • 2
    A common convention is to use (string,error), with the understanding that a non-nil error means the string is meaningless. It is also possible to return (string,bool,error) to denote the existence or non-existence of the string. Returns a *string is also ok. With a *os.File return type, the compiler inserts the redirection automatically. If you had a function that took File, you would've passed *f. Commented Aug 20, 2022 at 17:00
  • @kidfrom empty strings don't cause panics unless you attempt to index into them. Commented Aug 20, 2022 at 17:01
  • @mkopriva noted. I will use (string,error) then if that is the idiomatic way in Go. Anyway, I can't see os source code, so I am guessing that somewhere in os.Open function it return *os.File, it just happen that I can't do the same with return *string Commented Aug 20, 2022 at 17:06

1 Answer 1

1

To summarize the various comments:

You can simply return an empty string instead of a pointer.

func Convert(r io.Reader) (string, error) {
    dat := "hello"
    return dat, nil
}

func ConvertPath(path string) (string, error) {
    f, err := os.Open(path)
    if err != nil {
        return "", err
    }
    defer f.Close()

    return Convert(f)
}

func main() {
  dat, err := ConvertPath("/tmp/dat2")
  if err != nil {
    panic(err)
  }
  fmt.Println(dat)
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.