5

I know Go idiomatic don't have setter and getter. But I need to restrict value of variables in Go.

I defined new type

type MyNewStringType string

And variables, that was defined as MyStringType, need to restrict value.

Variables of MyStringType can have only 3 values: "Yes", "No", "I don't know"

How can I do it in Golang? In Java, C++ I have setter and getter, but in Golang is not normal.

I know, I can create

type MyNewStringType struct {
   Variable string
}

and create

func(m *MyNewStringType) SetVariable(newVar string) error {
  if newVar == "Yes" || newVar == "No" || newVar == "I don't know" {
    m.Variable = newVar
    return nil
  } else {
    return errors.New("Wrong value")
  }

But I think it's wrong way.

Flimzy
  • 68,325
  • 15
  • 126
  • 165
arzonus
  • 111
  • 1
  • 6
  • 9
    I believe it's a right way. Just make the variable lower case so it's not accessible outside of package. – Alexander Trakhimenok Nov 09 '16 at 10:12
  • 3
    Related / possible duplicate of [Golang: Creating a Constant Type and Restricting the Type's Values](http://stackoverflow.com/questions/37385007/golang-creating-a-constant-type-and-restricting-the-types-values). – icza Nov 09 '16 at 10:14
  • You might want to look at this http://stackoverflow.com/questions/14426366/what-is-an-idiomatic-way-of-representing-enums-in-go – Franck Jeannin Nov 09 '16 at 10:23
  • Does this answer your question? [Creating a Constant Type and Restricting the Type's Values](https://stackoverflow.com/questions/37385007/creating-a-constant-type-and-restricting-the-types-values) – Aruna Herath Mar 25 '21 at 12:15

2 Answers2

0

A nicer way of implementing this could be to allow any value, and then validating when the value is used. A short example:

package main

import (
  "fmt"
  "os"
)

func main() {
  fmt.Println("First try")
  if err := doSomething("foo"); err != nil {
    fmt.Fprintf(os.Stderr, "%v\n", err)
  }

  fmt.Println()

  fmt.Println("Second try")
  if err := doSomething("Yes"); err != nil {
    fmt.Fprintf(os.Stderr, "%v\n", err)
  }
}

func doSomething(s string) error {
  switch s {
  case "Yes", "No", "I don't know":
    fmt.Println("Success!")
    return nil
  default:
    return fmt.Errorf("unsupported value: %q", s)
  }
}

Output:

First try
unsupported value: "foo"

Second try
Success!

https://play.golang.org/p/nt8J9wdlZkp

If you insist on implementing it in the way you suggest, perhaps your SetVariable method would become a little bit tidier if you used a switch statement as in the above example.

jsageryd
  • 3,682
  • 18
  • 32
-5

Short awnser:

type MyString string
const (
    YES MyString = "yes"
    NO = "no"
    DONTKNOW = "i dont know"
)

func foo(arg MyString){
    fmt.Print(arg)
}

foo(YES) //success, prints "yes"

foo("jop") //fails to compile
user2326871
  • 221
  • 1
  • 8
  • 3
    This doesn't actually solve the problem. In the case of `foo("jop")` `"jop"` will be case to `MyString` type, so it will compile. – leesio Apr 17 '18 at 13:29