How to convert interface{} to bytes.Buffer?
Minimal example
package main
import (
"bytes"
"fmt"
)
func ToJson5(any interface{}) string {
if any == nil {
return `''`
}
switch any.(type) {
case bytes.Buffer: // return as is
return any.(bytes.Buffer).String()
// other types works fine
}
return ``
}
func main() {
x := bytes.Buffer{}
fmt.Println(ToJson5(x))
}
The errors was:
main.go:14: cannot call pointer method on any.(bytes.Buffer)
main.go:14: cannot take the address of any.(bytes.Buffer)
When changed to bytes.Buffer{} (that I think less correct), the error was:
main.go:13: bytes.Buffer literal (type bytes.Buffer) is not a type
main.go:14: bytes.Buffer literal is not a type
You can use a Short variable declaration in the Type switch to have the typed value in the case branches:
switch v := any.(type) {
case bytes.Buffer: // return as is
return v.String() // Here v is of type bytes.Buffer
}
Try it on the Go Playground.
Quoting form the spec:
The TypeSwitchGuard may include a short variable declaration. When that form is used, the variable is declared at the beginning of the implicit block in each clause. In clauses with a case listing exactly one type, the variable has that type; otherwise, the variable has the type of the expression in the TypeSwitchGuard.
Related
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)
...
If I have function like this
func TestMethod ( d interface{} ) {
}
If I am calling this as
TestMethod("syz")
Is this pass by value or pass by pointer ?
To summarise some of the discussion in the comments and answer the question:
In go everything in Go is passed by value. In this case the value is an interface type, which is represented as a pointer to the data and a pointer to the type of the interface.
This can be verified by running the following snippet (https://play.golang.org/p/9xTsetTDfZq):
func main() {
var s string = "syz"
read(s)
}
//go:noinline
func read(i interface{}) {
println(i)
}
which will return (0x999c0,0x41a788), one pointer to the data and one pointer to the type of interface.
Updated: Answer and comments above are correct. Just a lite bit of extra information.
Some theory
Passing by reference enables function members, methods, properties,
indexers, operators, and constructors to change the value of the
parameters and have that change persist in the calling environment.
Little code sniped to check how function calls work in GO for pointers
package main_test
import (
"testing"
)
func MyMethod(d interface{}) {
// assume that we received a pointer to string
// here we reassign pointer
newStr := "bar"
d = &newStr
}
func TestValueVsReference(t *testing.T) {
data := "foo"
dataRef := &data
// sending poiner to sting into function that reassigns that pointer in its body
MyMethod(dataRef)
// check is pointer we sent changed
if *dataRef != "foo" {
t.Errorf("want %q, got %q", "bar", *dataRef)
}
// no error, our outer pointer was not changed inside function
// confirms that pointer was sent as value
}
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.
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.
In my actual code, I'm parsing an XML document using encoding/xml, and I basically have a bunch of nested structures of the following form — all of which may occur multiple times, except the top-level statements element:
statements
statement
opcode
args
pre
post
I'm fairly new to Go, and I'm clearly misunderstanding how interface{} (the empty interface) works:
.\stmtgen.go:58: cannot use print_name (type func(Statement)) as type func(interface {}) in argument to performAction
.\stmtgen.go:58: cannot use slist (type []Statement) as type []interface {} in argument to performAction
Relevant example code:
package main
import "fmt"
// Actually a structure in my code, but this suffices for demonstration.
type Opcode int
// A Statement has a Name and multiple Opcodes may use this Name.
type Statement struct {
Name string
Opcodes []Opcode
}
// Print the statement name.
func print_name(stmt Statement) {
fmt.Println(stmt.Name)
}
// Perform an action on each item of a collection.
func performAction(action func(interface{}), v []interface{}) {
for i := range v {
action(v[i])
}
}
func main() {
slist := make([]Statement, 3)
slist[0] = Statement{"Statement 1"}
slist[1] = Statement{"Statement 2"}
slist[2] = Statement{"Statement 3"}
//ERROR HERE
performAction(print_name, slist)
}
Must I create functions to print the values for every single type?
An empty interface{} can contain any value and passed around as the type interface{}. when you need the value from it, you can perform a type assertion like this:
var anyValue interface{}
anyValue = "hello"
strValue := anyValue.(string)
If anyValue is not of the type being asserted then it will cause a panic
the type assertion can also be used to return a bool if the interface is of that type with a multiple return
strValue, ok := anyValue.(string)
if ok {
//anyValue contains a string!
}
If you dont know the type of the interface, you can use a switch to determine it's type like this:
switch val := anyValue.(type) {
case string:
// anyValue contains a string
// and val is a string
break
case int:
// anyValue contains an int
// and val is and int
break
default:
//unhandled interface type
}
Hopefully this makes the empty interface{} type clearer.
interfaces{...} which have methods declared in them are different, they can not have members (like structs can), only methods, and their underlying type must implement all the methods declared in the interface. You could have an interface actionPerformer (interface names should have the suffix "er" as they are doing something)
type actionPerformer interface {
action(interface{})
}
A type that implements all the methods in an interface can be cast to that interface type, then if you call one of those methods on the interface, it will run the method on the underlying type.
For example, if the Statement struct implements the action(interface{}) method, the Statement struct can be cast to an actionPerformer type and if the action(interface{}) function is called on the actionPerformer, the action function on the Statement struct is run. So you could have multiple types that all have the action(interface{}) method and they can all be cast to an actionPerformer which you can call the action function on.
func (code Opcode) action(arg interface{}) {
fmt.Println(arg.(int) + int(code))
}
func (stmt Statement) action(arg interface{}) {
fmt.Println(arg.(string), stmt.Name)
}
stmt := Statement{"Statement 1", nil}
stmtActionPerformer := actionPerformer(stmt)
opcode := Opcode(5)
opcodeActionPerformer := actionPerformer(opcode)
stmtActionPerformer.action("hello") // will print "hello "+whatever the statements name is
opcodeActionPerformer.action(2) //will print be 7
Type assertions can still be used on these types of interface e.g.
stmt := stmtActionPerformer.(Statement)
fmt.Println(stmt.Name)
This is a contrived example, but with this in mind, you might want to write your code using interfaces like this.
Remember casting between interfaces is costly, so should be done sparingly, however they are a powerful tool when used correctly.
For your example, a simple printNames function would be much more efficient than all that interface casting (note that in golang, names should be in the CamelCase format, not using underscores)
func printNames(stmts []Statement) {
for _, stmt := range stmts {
fmt.Println(stmt.Name)
}
}
It might also be useful to have a type StatementList and add methods to it:
type StatementList []Statement
func (list StatementList) printNames() {
for _, stmt := range list {
fmt.Println(stmt.Name)
}
}
Getting the hang of this stuff make golang a lot more fun, hope this helps :)
You have to declare the parameters of performAction exactly same like the arguments type.
func performAction(action func(Statement), v []Statement) {
for i := range v {
action(v[i])
}
}
Or you could use interface{} on all parameters instead. Then cast it according to the needs.
func performAction(action interface{}, v interface{}) {
for _, each := range v.([]Statement) {
action.(func(Statement))(each)
}
}
data with type []Statement cannot be assigned to []interface{}
also for type func(Statement) cannot be assigned to func(interface{})
Use interface{}, then cast it to the original type.
this works for me:
package main
import (
"fmt"
)
// Actually a structure in my code, but this suffices for demonstration.
type Opcode int
// A Statement has a Name and multiple Opcodes may use this Name.
type Statement struct {
Name string
Opcodes []Opcode
}
// Print the statement name.
func print_name(stmt interface{}) {
if s, ok := stmt.(Statement); !ok {
panic("typ err")
} else {
fmt.Println(s.Name)
}
}
// Perform an action on each item of a collection.
func performAction(action func(interface{}), v []interface{}) {
for i := range v {
action(v[i])
}
}
func main() {
slist := make([]interface{}, 3)
slist[0] = Statement{"Statement 1", nil}
slist[1] = Statement{"Statement 2", nil}
slist[2] = Statement{"Statement 3", nil}
performAction(print_name, slist)
/*output:
Statement 1
Statement 2
Statement 3
*/
}