2

I have some code in the playground: sample code

I pass a two dimension string slice into a function test, which can accept variadic arguments, and in test() I can get the first argument's underlying type, but how can I convert it back to its underlying type? because I have to iterate on its underlying type

I don't like to hard code it like:

if reflect.TypeOf(args[0]).String() == "[][]string" { val := args[0].([][]string) } 

the question is if I know its type string is "[][]string" or something else, how can I convert it to the type?

I post the full code here, and add some comments:

package main import ( "reflect" "fmt" ) func test(args ...interface{}) { fmt.Println("type", reflect.TypeOf(args[0])) // here will be a compile error, because args[0]'type now is interface{}, // not a slice, though it's underlying type is slice for i, v := range args[0] { } // so, how could I convert args[0] to [][]string when I get its type // string "[][]string" ? // I know use type assertion is possible, but you must guess the possible // type the args[0] will be. // is there a way to do it from a type's string representation to the // actual type? // so I can write code like this: // val := args[0].(reflect.TypeOf(args[0]).String()), which is very general } func main() { arr := [][]string{{"asd", "sd", "rt"}, {"34","gf","gf"}} test(arr) } 
2
  • This looks like an "A B question". Can you explain what you intend to do afterwards with your code ? Commented Jan 23, 2014 at 15:30
  • Are you sure that you really need reflection and can't get away with type assertion/switch? Commented Jan 23, 2014 at 16:18

3 Answers 3

4

Another variation on ANisus answer :

package main import "fmt" func main() { var x interface{} = [][]string{{"Hello"}, {"World", "!"}} if y, ok := x.([][]string); ok { fmt.Printf("%v", y) } } 

http://play.golang.org/p/tGYbhzuUnr


Otherwise, use the reflect package :

import ( "fmt" "reflect" ) func process(i interface{}) { fmt.Printf("Processing %v\n", i) if reflect.TypeOf(i).Kind() == reflect.Slice { v := reflect.ValueOf(i) for i := 0; i < v.Len(); i++ { process(v.Index(i).Interface()) } } } func main() { var x = [][]string{{"Hello"}, {"World", "!"}} var y = []int{2,3,5,7,9} var z = 'H' process(x) process(y) process(z) } 

http://play.golang.org/p/MAqIgxzLuC

Sign up to request clarification or add additional context in comments.

3 Comments

The question still stands : what do you want to do with val ?
I want to use a for loop to loop over its elements, so I can process each of them
Use the reflect package
3

I am not entirely sure what you wish to achieve.

If you pass in a [][]string as the first argument, in order to iterate over it, you must do a type assertion or type switch:

switch val := args[0].(type) { case [][]string: // Do what you want with val which is of type [][]string } 

You can read more about type switches in the Go specifications: http://golang.org/ref/spec#Switch_statements

If you try to pass the [][]string slice unchanged to test:

test(arr...) // Attempt to pass the array unchanged. 

this will fail. This is due to [][]string not being assignable to []interface{}. The Go specification states:

If the final argument is assignable to a slice type []T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.

6 Comments

thanks to your anwser. I know I can convert it through type assertion, but when do it in this way, you have to write the switch case, right? you must guess what the cases you'll encounter. So what I want is that if I know the type string, for example "[][]string", I can convert the interface{} to [][]string
I don't know if I make the question clear, you can think that I want to get the type [][]string from its string representation "[][]string"
@zhaozhi I am afraid I don't really understand. Do you want to turn [][]string to a []interface{} so that you can iterate over each []string? You can use reflection to see if the interface{} contains a slice, and then iterate over it, without the use of type assertion.
in the function test(), I want to convert args[0] from its type(interface{}) to its underlying type([][]string). once you get its type string, i.e "[][]string", can you finish this convertion without use type assertion?
@zhaozhi no, you need to do a type assertion to get a concrete type.
|
1

It is not possible to use a dynamic value for a type assertion, so

foo.(reflect.TypeOf(bar)) 

or something similar will not work. This is because types are not first class citizens and can't be stored in a variable.

You always have to write explictly which type you want the interface value to be, either by using a type assertion or a type switch.

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.