cannot convert data (type interface {}) to type string: need type assertion - go

I am pretty new to go and I was playing with this notify package.
At first I had code that looked like this:
func doit(w http.ResponseWriter, r *http.Request) {
notify.Post("my_event", "Hello World!")
fmt.Fprint(w, "+OK")
}
I wanted to append newline to Hello World! but not in the function doit above, because that would be pretty trivial, but in the handler afterwards like this below:
func handler(w http.ResponseWriter, r *http.Request) {
myEventChan := make(chan interface{})
notify.Start("my_event", myEventChan)
data := <-myEventChan
fmt.Fprint(w, data + "\n")
}
After go run:
$ go run lp.go
# command-line-arguments
./lp.go:15: invalid operation: data + "\n" (mismatched types interface {} and string)
After a little bit of Googling I found this question on SO.
Then I updated my code to:
func handler(w http.ResponseWriter, r *http.Request) {
myEventChan := make(chan interface{})
notify.Start("my_event", myEventChan)
data := <-myEventChan
s:= data.(string) + "\n"
fmt.Fprint(w, s)
}
Is this what I was supposed to do? My compiler errors are gone so I guess that's pretty good? Is this efficient? Should you do it differently?

According to the Go specification:
For an expression x of interface type and a type T, the primary expression x.(T) asserts that x is not nil and that the value stored in x is of type T.
A "type assertion" allows you to declare an interface value contains a certain concrete type or that its concrete type satisfies another interface.
In your example, you were asserting data (type interface{}) has the concrete type string. If you are wrong, the program will panic at runtime. You do not need to worry about efficiency, checking just requires comparing two pointer values.
If you were unsure if it was a string or not, you could test using the two return syntax.
str, ok := data.(string)
If data is not a string, ok will be false. It is then common to wrap such a statement into an if statement like so:
if str, ok := data.(string); ok {
/* act on str */
} else {
/* not string */
}

Type Assertion
This is known as type assertion in golang, and it is a common practice.
Here is the explanation from a tour of go:
A type assertion provides access to an interface value's underlying concrete value.
t := i.(T)
This statement asserts that the interface value i holds the concrete type T and assigns the underlying T value to the variable t.
If i does not hold a T, the statement will trigger a panic.
To test whether an interface value holds a specific type, a type assertion can return two values: the underlying value and a boolean value that reports whether the assertion succeeded.
t, ok := i.(T)
If i holds a T, then t will be the underlying value and ok will be true.
If not, ok will be false and t will be the zero value of type T, and no panic occurs.
NOTE: value i should be interface type.
Pitfalls
Even if i is an interface type, []i is not interface type. As a result, in order to convert []i to its value type, we have to do it individually:
// var items []i
for _, item := range items {
value, ok := item.(T)
dosomethingWith(value)
}
Performance
As for performance, it can be slower than direct access to the actual value as show in this stackoverflow answer.

//an easy way:
str := fmt.Sprint(data)

As asked for by #ρяσѕρєя an explanation can be found at https://golang.org/pkg/fmt/#Sprint. Related explanations can be found at https://stackoverflow.com/a/44027953/12817546 and at https://stackoverflow.com/a/42302709/12817546. Here is #Yuanbo's answer in full.
package main
import "fmt"
func main() {
var data interface{} = 2
str := fmt.Sprint(data)
fmt.Println(str)
}

In addition to other answers, I think it's good to have a look at "type switch":
package main
import "fmt"
func printType(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("type of %v is %v\n", i, v)
// type of 21 is int
case string:
fmt.Printf("type of %v is %v\n", i, v)
// type of hello is string
default:
fmt.Printf("type of %v is %v\n", i, v)
// type of true is bool
}
}
func main() {
printType(21)
printType("hello")
printType(true)
}
I hope it helps.
More information: https://go.dev/tour/methods/16

Related

instantiate by reflection

Given a function with a parameter (that is a pointer to a struct) I want to instantiate a type of this parameter.
For example, for this function:
func MyFunction(myStruct *MyStruct) {}
using reflection I want to create a variable that contains exactly same as x := &MyStruct{} would contain.
This is the code example:
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
}
func main () {
reflectedFunction := reflect.TypeOf(MyFunction)
argType := reflectedFunction.In(0)
reflectedParameter := reflect.New(argType)
actual := reflectedParameter.Interface()
fmt.Println(actual)
expected := &MyStruct{}
fmt.Println(expected)
}
func MyFunction(myStruct *MyStruct) {
}
If you execute it, you'll see that they contain different info:
0xc00000e028 // actual
&{} // expected
This question isn't about why I would like to do this, so please avoid recommending not doing it, etc.
In your code, actual is a interface{} value containing a *MyStruct. As the name and documentation indicate, reflectedParameter.Interface() returns an interface{}.
using reflection I want to create a variable that contains exactly same as x := &MyStruct{} would contain.
Then you'll have to type assert it:
actual := reflectedParameter.Elem().Interface().(*MyStruct)
reflect.New creates a pointer to a new zero value of the reflected type. In your example that type is already a *MyStruct, so the value of your actual winds up being a representation of a **MyStruct, as seen in https://play.golang.org/p/Nyuc0mYmgkZ. Taking the .Elem() of that results in the correct type again, but you end up with a nil pointer (*MyStruct)(nil).
You need to take the .Elem() if that first type if you want to create a new pointer value.
reflectedParameter := reflect.New(argType.Elem())
https://play.golang.org/p/QzwTFUH3HTs
reflectedFunction := reflect.TypeOf(MyFunction)
argType := reflectedFunction.In(0)
reflectedParameter := reflect.New(argType.Elem())
actual := reflectedParameter.Interface()
fmt.Printf("%#v\n", actual)
expected := &MyStruct{}
fmt.Printf("%#v\n", expected)
Which prints
&main.MyStruct{}
&main.MyStruct{}

Golang type switch requires (redundant) type assertion

I would like to use a type switch to call a type specific parsing function
https://play.golang.org/p/2xj_owLL4ZK
package main
import (
"fmt"
)
func main() {
var value interface{}
value = "I am a string"
switch v := value.(type) {
case string:
parseString(value)
default:
fmt.Printf("I don't know about type %T!\n", v)
}
}
func parseString(s string) {
fmt.Println(s)
}
However this does not compile because it's missing a type assertion:
cannot use value (type interface {}) as type string in argument to parseString: need type assertion
Adding a type assertion fixes the error.
https://play.golang.org/p/p0nYNEEJb0Z
package main
import (
"fmt"
)
func main() {
var value interface{}
value = "I am a string"
switch v := value.(type) {
case string:
s, ok := value.(string)
if ok {
parseString(s)
}
default:
fmt.Printf("I don't know about type %T!\n", v)
}
}
func parseString(s string) {
fmt.Println(s)
}
But this feels redundant. I am now checking twice, whether the value is a string.
Should I choose between a type switch and type assertion? Perhaps there is a less redundant way to do this? The example is contrived. There could be many types, which is why a type switch seemed like clean solution...until I started adding type asseertions.
Update
This question has received multiple downvotes. I think this misses the confusing nature of Go's type switch where it appears (initially) as if the value being switched on is the type, not the value.
switch v := value.(type) {
case string:
// ...
case int:
// ...
}
I'm new to Go and incorrectly assumed v was the type. If I ran into this problem when writing Go for this first time, others may too?
Use the value you declared in the switch:
switch v := value.(type) {
case string:
// v is string here
parseString(v)
...

Go Reflect field name to specific interface

I have a struct type with a number of fields that all implement a Renderer interface. The field types implement the interface with pointer receivers. I would like to have a function that takes the field name and calls the Render method on that field. I am able to locate the field and get lots of information about it, but doing the type assertion seems to be biting me because of the pointer receivers. Here's some code that shows my problem:
package main
import (
"fmt"
"reflect"
)
type Renderer interface {
Render()
}
type First struct {
ExampleField Field
}
type Field []int
func (f *Field) Render() {
fmt.Println("Hello from first")
}
func main() {
f := First{
Field{1, 2, 3},
}
f.ExampleField.Render()
renderField("ExampleField", &f)
renderField2("ExampleField", &f)
}
func renderField(field string, f *First) {
structVal := reflect.ValueOf(*f)
renderType := reflect.TypeOf((*Renderer)(nil)).Elem()
fieldToRender := structVal.FieldByName(field)
fieldPtr := reflect.PtrTo(fieldToRender.Type())
fmt.Printf("Implements? %v\n", fieldPtr.Implements(renderType))
fmt.Printf("Addressable? %v\n", fieldToRender.CanAddr())
fieldInter := fieldToRender.Interface()
if renderer, ok := fieldInter.(Renderer); ok {
// Pointer receiver so this never gets called
fmt.Print("Able to cast")
renderer.Render()
}
}
func renderField2(field string, f *First) {
structVal := reflect.ValueOf(*f)
fieldToRender := structVal.FieldByName(field)
vp := reflect.New(reflect.TypeOf(fieldToRender))
vp.Elem().Set(reflect.ValueOf(fieldToRender))
vpAddr := vp.Elem().Addr()
typeVal := vpAddr.Interface()
fmt.Println(typeVal) // <main.Field Value>⏎
renderer := typeVal.(Renderer)
renderer.Render()
// interface conversion: *reflect.Value is not main.Renderer: missing method Render
}
renderField2 seems to get me close but Addr() gives me a *Reflect.Value and when I call Interface() that seems to be the underlying type instead. If I switch to a non-pointer receiver then the first function works. I found reflect value Interface and pointer receiver which seems to be almost exactly what I'm asking, and the question is answered but if I actually call the isZeroer method presented in the playground link it's always false so it doesn't actually seem to answer the question.
It seems like Addr is the key because it specifically mentions pointer receivers but I'm struggling to coerce it back into an interface.
Use this code:
func renderField(name string, f *First) {
structVal := reflect.ValueOf(f).Elem()
field := structVal.FieldByName(name).Addr().Interface()
if renderer, ok := field.(Renderer); ok {
renderer.Render()
}
}
The key point is to change:
structVal := reflect.ValueOf(*f)
to:
structVal := reflect.ValueOf(f).Elem()
The statement used in the question creates a non-addressable struct value. The fields in a non-addressable struct are also not addressable, therefore it's not possible to access the pointer receiver on the fields.
The statement used in this answer creates an addressable struct value.

Does type assertion change the value in go?

Go newbie here.
I have a map where the key arguments should be []string.
However, if I try to use the value directly arguments := m["arguments"] it doesn't seem to be the right type. When used later to append to another slice with arguments... I get Cannot use 'arguments' (type interface{}) as type []string.
I fixed this by chaning the assignment to a type check arguments, _ := m["arguments"].([]string). That works, but I'm not sure why. Is type assertion doing conversion as well?
The full example is below:
import (
"github.com/fatih/structs"
"strings"
)
var playbookKeyDict = map[string]string{
"Playbook": "",
"Limit" : "--limit",
"ExtraVars" : "--extra-vars",
}
type Playbook struct {
Playbook string `json:"playbook" xml:"playbook" form:"playbook" query:"playbook"`
Limit string `json:"limit" xml:"limit" form:"limit" query:"limit"`
ExtraVars string `json:"extra-vars" xml:"extra-vars" form:"extra-vars" query:"extra-vars"`
Arguments []string `json:"arguments" xml:"arguments" form:"arguments" query:"arguments"`
Args []string
}
func (p *Playbook) formatArgs() {
// is it worth iterating through directly with reflection instead of using structs import?
// https://stackoverflow.com/questions/21246642/iterate-over-string-fields-in-struct
m := structs.Map(p)
// direct assignment has the wrong type?
// arguments := m["arguments"]
arguments, _ := m["arguments"].([]string)
delete(m, "arguments")
for k, v := range m {
// Ignore non-strings and empty strings
if val, ok := v.(string); ok && val != "" {
key := playbookKeyDict[k]
if key == "" {
p.Args = append(p.Args, val)
} else {
p.Args = append(p.Args, playbookKeyDict[k], val)
}
}
}
p.Args = append(p.Args, arguments...)
}
Type assertion is used to get a value wrapped around using interface.
m := structs.Map(p)
Map(v interface{}){}
Map function is actually taking interface as its argument in the case stated. It is wrapping the type which is []string and its underlying value which is slice. The type can be checked using Relection reflect.TypeOf().
func TypeOf(i interface{}) Type
According to Russ Cox blog on Interfaces
Interface values are represented as a two-word pair giving a pointer
to information about the type stored in the interface and a pointer to
the associated data.
As specified in Golang spec
For an expression x of interface type and a type T, the primary
expression
x.(T)
asserts that x is not nil and that the value stored in x is of type T.
The notation x.(T) is called a type assertion.
For the error part:-
Cannot use 'arguments' (type interface{}) as type []string
We first needs to get the underlying value of type []string from interface using type assertion.

Type assertion when returning an interface

I'm new to golang; however based on my current knowledge I understand that a value-type and a reference-type can both fulfill an interface. But it seems in regards to type assertion, how you return a struct does matter. See the following:
package main
import (
"fmt"
)
type SomeError interface {
Error() string
}
type ConcreteError struct{}
func (ConcreteError) Error() string {
return "?"
}
func returnPointer() SomeError {
return &ConcreteError{}
}
func returnVal() SomeError {
return ConcreteError{}
}
func main() {
pointer := returnPointer()
value := returnVal()
_, pointerWithPointer := pointer.(*ConcreteError);
_, pointerWithValue := pointer.(ConcreteError);
_, valueWithValue := value.(ConcreteError);
_, valueWithPointer := value.(*ConcreteError)
fmt.Printf("Returning a pointer, assert using (*ConcreteError): %v\n", pointerWithPointer); // true
fmt.Printf("Returning a pointer, assert using (ConcreteError): %v\n", pointerWithValue); // false
fmt.Printf("Returning a value, assert using (ConcreteError): %v\n", valueWithValue); // true
fmt.Printf("Returning a value, assert using (*ConcreteError): %v\n", valueWithPointer); // false
}
So if my understanding is correct, the user needs to know how the struct is returned to correctly assert its type?
I'm going to guess and assume the standard practice in golang is to always return a pointer to a struct(i.e like *PathError)?
link to play: here
So if my understanding is correct, the user needs to know how the struct is returned to correctly assert its type?
It depends. If you need the type assertion to pass - you surely need to know the exact type of the value. a and *a are different types.
I'm going to guess and assume the standard practice in golang is to always return a pointer to a struct(i.e like *PathError)?
No.

Resources