84

In this bizarre example, someone has created a new type which is really just a string:

type CustomType string

const (
        Foobar CustomType = "somestring"
)

func SomeFunction() string {
        return Foobar
}

However, this code fails to compile:

cannot use Foobar (type CustomType) as type string in return argument

How would you fix SomeFunction so that it is able to return the string value of Foobar ("somestring") ?

5
  • 7
    Creating a type that's just a string is not all that bizarre. For example, if a you know that certain string is always a country name you could create a type Country string; this will make the code easier to read. Commented Aug 26, 2017 at 6:06
  • 2
    @Akavall How about restricting Country type to a known list of values? Can we do that? Commented Nov 4, 2018 at 8:58
  • 1
    Is this basically go's way of doing enums? Commented Sep 12, 2022 at 16:32
  • 4
    How can we do the opposite of this, casting "string" to "CustomType"? I hit "invalid operation: (someString) (value of type string) is not an interface" with code someString.(CustomType) Edit: "CustomType(someString)" seems to do the trick. It's hard to find the right documentation on casting with alias types, I only find doc for interfaces. Commented Oct 11, 2022 at 7:33
  • For those who asked: "is this the way Go implements enums?" the answer is almost. A full example is too big for this comment, so here goes a link: builtin.com/software-engineering-perspectives/golang-enum — if it's broken, look it up on the Internet Archive. It's a warped way of thinking about things, but it's as effective as enums in other languages (i.e, the checks also occur at compile time). Also read the suggested answer about defining a helper String() function; it's an idiomatic convention. Commented Aug 12 at 16:16

4 Answers 4

79

Convert the value to a string:

func SomeFunction() string {
        return string(Foobar)
}
Sign up to request clarification or add additional context in comments.

2 Comments

Very useful if one hasn't control over the string type-alias; in those sitations adding a String method is impossible.
Hi, I've tried to convert a type "ULID" to string using this cast. It does have a method "String" implementing the "Stringer" method. Why cast still doesn't work? Casting to "string" is not related to implementing the "Stringer" interface?
37

Better to define a String function for the Customtype - it can make your life easier over time - you have better control over things as and if the structure evolves. If you really need SomeFunction then let it return Foobar.String()

   package main

    import (
        "fmt"
    )

    type CustomType string

    const (
        Foobar CustomType = "somestring"
    )

    func main() {
        fmt.Println("Hello, playground", Foobar)
        fmt.Printf("%s", Foobar)
        fmt.Println("\n\n")
        fmt.Println(SomeFunction())
    }

    func (c CustomType) String() string {
        fmt.Println("Executing String() for CustomType!")
        return string(c)
    }

    func SomeFunction() string {
        return Foobar.String()
    }

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

1 Comment

On the comments for the OP, it was asked if this is the way of creating enums in Go. And, indeed, it's one way (probably the most idiomatic way) of doing just that. Having a CustomType means that not only one constant can be defined; you can use the iota pattern to enumerate all possible valid CustomTypes — and these will be enforced at compile-time, just as expected from statically compiled languages. The String() convention you show is then typically used with a switch{} to convert the object's value (which is a constant of type CustomType) into a human-readable string.
12

For every type T, there is a corresponding conversion operation T(x) that converts the value x to type T. A conversion from one type to another is allowed if both have the same underlying type, or if both are unnamed pointer types that point to variables of the same underlying type; these conversions change the type but not the representation of the value. If x is assignable to T, a conversion is permitted but is usually redundant. - Taken from The Go Programming Language - by Alan A. A. Donovan

As per your example here are some of the different examples which will return the value.

package main

import "fmt"

type CustomType string

const (
    Foobar CustomType = "somestring"
)

func SomeFunction() CustomType {
    return Foobar
}
func SomeOtherFunction() string {
    return string(Foobar)
}
func SomeOtherFunction2() CustomType {
    return CustomType("somestring") // Here value is a static string.
}
func main() {
    fmt.Println(SomeFunction())
    fmt.Println(SomeOtherFunction())
    fmt.Println(SomeOtherFunction2())
}

It will output:

somestring
somestring
somestring

The Go Playground link

Comments

3

You can convert like this:

var i int = 42 var f float64 = float64(i)

check here

you can return like this:

return string(Foobar)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.