Assign method to custom types in Golang

Asked

Viewed 71 times

0

I have a code where I need to perform several replaces and for that I did so as follows:

exemplo := "Olá, meu nome é xpto, na verdade xpto da silva xpto"
formated := strings.Replace(exemplo, "xpto", "Fulano")
formated := strings.Replace(formated, "Olá", "oi")

fmt.Println(formated)

To try to make it more "friendly" I decided to create a variable of type string that allows me to use a chained "replace" method, which would look like this:

exemplo := "Olá, meu nome é xpto, na verdade xpto da silva xpto"
formated := custom(exemplo).replace("xpto", "fulano").replace("olá", "oi")

For that I made:

type custom string

func (c *custom) replace(old, new string) custom {
    content := string(*c)
    return custom(strings.Replace(content, old, new, -1))
}

func main() {
    text := custom("Olá, nome, Olá, nome")
    fmt.Println(text.replace("Olá", "oi").replace("nome", "nombre"))

}

When executing code with only 1 replace it runs successfully, but if I try to chain another replace as in the above example I get the error that it is not possible to access the pointer or the address of text.replace("Olá", "oi"), I believe this error is generated because when I return the "custom" in replace no memory address is assigned to it.

cannot call Pointer method on text.replace("Hello", "hi")

cannot take the address of text.replace("Hello", "hi")

I’ve already tried to assign the return of replace for a variable to generate a memory address:

func (c *custom) replace(old, new string) *custom {
    content := string(*c)
    formated := custom(strings.Replace(content, old, new, -1))

    return &formated
}

Only this way, the Println in main will display the address and not the value.

How can I use the value returned from a function in a chained method?

1 answer

1


You can create a pointer, as follows:

func (c *custom) replace(old, new string) *custom {
    content := string(*c)
    r := custom(strings.Replace(content, old, new, -1))
    return &r
}

So use it as:

func main() {
    text := custom("Olá, nome, Olá, nome")
    fmt.Println(*text.replace("Olá", "oi").replace("nome" ,"xx"))
}

This will work as expected, use the * to recover the value, in the print.

Another option is precisely not to use references/pointers:

func (c custom) replace(old, new string) custom {
    return custom(strings.Replace(string(c), old, new, -1))
}

func main() {
    text := custom("Olá, nome, Olá, nome")
    fmt.Println(text.replace("Olá", "oi").replace("nome" ,"xx"))
}

Test this on https://play.golang.org/p/mrQPxpqDL8s


What is the difference between one and the other? Basically if you use (c *custom) you are saying that the input is a reference, not the value.

Soon, if you do:

func (c *custom) replace(old, new string) custom

You expect an entry as a reference, but it has as output the value itself. Golang tries to "convert automatically" (he uses the reference instead of the value itself), see that it works:

text := custom("Olá, nome, Olá, nome")
x := text.replace("Olá", "oi")
y := x.replace("nome", "nombre")

fmt.Println(y)

Variables are addressable, it is possible to create the pointer, with &x. The problem is that in Golang you do not allow creating pointers of anything, this is invalid:

fmt.Println( (&text.replace("Olá", "oi")).replace("nome", "nombre") )

Note that gives the same error, even if you do:

fmt.Println( (&text.replace("Olá", "oi")) )

This is precisely what Go tries to do internally, and is the cause of "cannot take the address of text.replace("Hello", "hi")".

According to the documentation under "Address Operator" you can only create references of variables, Slices and the like.

Already using the c custom you expect the value itself, not his pointer, so it will work.

  • I thought I could only access a value if I used a pointer to define the method replace in: func (c *custom); the difference between using or not using a pointer on this part func (c *custom)?

  • @RFL, I edited to add this detail. It would be long in a comment.

  • Just remembering there are more differences, using the c custom you cannot change the original value, for example see here, This is precisely because it is not a pointer to the original value. But, to restrict myself in the difference in this particular case, not in all the differences, which even I do not know if I know all, ahaha.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.