panic: interface conversion: interface {} is **string, not string

13,339

Solution 1

You require to assert **string to get underlying value wrapped around interface{}. And then dereference the value of string using double pointer.

package main

import (
    "fmt"
)

func main() {
    s := "ss"
    a := &s
    Modify(&a)
}

func Modify(s interface{}) {
     fmt.Println(**s.(**string))
}

Playground

Solution 2

If you can't avoid having a **string, this is how you can handle it: assert **string from the interface{} value (since this is what it contains), and then dereference the pointer which gives you *string which you again can dereference which gives you the string value.

func main() {
    s := "ss"
    a := &s

    fmt.Println("Before a:", *a)
    Modify(&a)
    fmt.Println("After a:", *a)
    fmt.Println("After s:", s)
}

func Modify(s interface{}) {
    sp := s.(**string)
    **sp = "modified"
}

Output (try it on the Go Playground):

Before a: ss
After a: modified
After s: modified

But know that if you already have a variable of *string type (which is a), you don't need to take and pass its address, you can pass it as-is (a *string value):

func main() {
    s := "ss"
    a := &s

    fmt.Println("Before a:", *a)
    Modify(a)
    fmt.Println("After a:", *a)
    fmt.Println("After s:", s)
}

func Modify(s interface{}) {
    sp := s.(*string)
    *sp = "modified"
}

Output again will be (try it on the Go Playground):

Before a: ss
After a: modified
After s: modified

Note that in both cases the value pointed by a changed to "modified", but the value of s also changed. This is because inside Modify() we modified the pointed-pointed value. If you only want a to change (more specifically the value pointed by a) but you don't want to change s, then inside Modify() you should only modify the value pointed by sp, which will be the variable a, but not the pointed-pointed value (which is s). In order to only change the pointed value, you have to assign a value of type *string to it:

func main() {
    s := "ss"
    a := &s

    fmt.Println("Before a:", *a)
    Modify(&a)
    fmt.Println("After a:", *a)
    fmt.Println("After s:", s)
}

func Modify(s interface{}) {
    sp := s.(**string)
    newValue := "modified"
    *sp = &newValue
}

This time the output will be (try it on the Go Playground):

Before a: ss
After a: modified
After s: ss

As you can see, Modify() modified the value pointed by a, but s remained unchanged.

Share:
13,339

Related videos on Youtube

Kumar Siva
Author by

Kumar Siva

Updated on June 04, 2022

Comments

  • Kumar Siva
    Kumar Siva almost 2 years

    How to convert double pointer string to string?

    In this example we can directly pass string argument. But I have double pointer string to string requirement in my app.

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        s := "ss"
        a := &s
        Modify(&a)
    }
    
    func Modify(s interface{}) {
        fmt.Println(s)
    
    }
    

    Playground: https://play.golang.org/p/d4hrG9LzLNO

  • Arian Saputra
    Arian Saputra almost 3 years
    how i can do this if i dont know what is the type of variable s on Modify method ? I'am stuck about 4 hours ago until now,,