2016-09-07 2 views
2

У меня есть функция.Как создать срез переменной типа в Go?

func doSome(v interface{}) { 

} 

Если я передам указатель кусочком структуры в функцию, функция должна заполнить срез.

type Color struct { 
} 
type Brush struct { 
} 

var c []Color 
doSome(&c) // after с is array contains 3 elements type Color 

var b []Brush 
doSome(&b) // after b is array contains 3 elements type Brush 

Возможно, мне нужно использовать отражение, но как?

ответ

1
func doSome(v interface{}) { 

    s := reflect.TypeOf(v).Elem() 
    slice := reflect.MakeSlice(s, 3, 3) 
    reflect.ValueOf(v).Elem().Set(slice) 

} 
1

typewitch !!

package main 
import "fmt" 

func doSome(v interface{}) { 
    switch v := v.(type) { 
    case *[]Color: 
    *v = []Color{Color{0}, Color{128}, Color{255}} 
    case *[]Brush: 
    *v = []Brush{Brush{true}, Brush{true}, Brush{false}} 
    default: 
    panic("unsupported doSome input") 
    } 
} 

type Color struct { 
    r uint8 
} 
type Brush struct { 
    round bool 
} 

func main(){ 
    var c []Color 
    doSome(&c) // after с is array contains 3 elements type Color 

    var b []Brush 
    doSome(&b) // after b is array contains 3 elements type Brush 

    fmt.Println(b) 
    fmt.Println(c) 

} 
+0

Нет! :) Его плохая практика. если я добавляю новый тип, функция doSome() нуждается в модификации. –

+0

Я думаю, что это * хорошая практика, потому что она заставляет вас явно выражать 'doSome()', а не предполагать поведение. Если вы хотите, чтобы doSome всегда создавал EMPTY-фрагменты, вы могли бы использовать 'b: = make ([] Brush, 3)' вместо 'doSome (& b)' – Plato

0

У Go нет дженериков. Ваши возможности:

Интерфейс диспетчеризации

type CanTraverse interface { 
    Get(int) interface{} 
    Len() int 
} 
type Colours []Colour 

func (c Colours) Get(i int) interface{} { 
    return c[i] 
} 
func (c Colours) Len() int { 
    return len(c) 
} 
func doSome(v CanTraverse) { 
    for i := 0; i < v.Len; i++ { 
     fmt.Println(v.Get(i)) 
    } 
} 

Тип переключатель, как @Plato предложил

func doSome(v interface{}) { 
    switch v := v.(type) { 
    case *[]Colour: 
    //Do something with colours 
    case *[]Brush: 
    //Do something with brushes 
    default: 
    panic("unsupported doSome input") 
    } 
} 

Отражение как fmt.Println() делать. Отражение очень мощное, но очень дорогое, код может быть медленным. Минимальный пример

func doSome(v interface{}) { 
    value := reflect.ValueOf(v) 
    if value.Kind() == reflect.Slice { 
     for i := 0; i < value.Len(); i++ { 
      element := value.Slice(i, i+1) 
      fmt.Println(element) 
     } 
    } else { 
     fmt.Println("It's not a slice") 
    } 
} 
Смежные вопросы