亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

切片和接口的類型轉換

切片和接口的類型轉換

Go
長風秋雁 2022-08-01 15:15:58
如果我傳遞了一個函數,我可以確定(通過其他方式)是一個切片,但不是它是什么切片,我該如何迭代它(最好不使用反射)?interface{}這是一個MCVE(從我的實際代碼中非常簡化)。 是一個循環訪問切片的函數,其類型在 main() 的調用堆棧中“丟失”。它試圖說“啊哈,一個切片,我將循環訪問它的一個接口切片{},并在每個值上調用傳入的onEach函數”。這失敗了,因為類型“轉換”失敗了,因此:forEachpanic: interface conversion: interface {} is []string, not []interface {}我非常清楚為什么類型“轉換”失敗,即它不是真正的類型轉換,而是一個斷言。但是,給定(如果只有我可以迭代)我可以斷言每個切片成員,這在原則上應該是可行的。讓我們假設我實際上想要一個可以做到這一點的迭代器(而不是一個,等等)。有沒有一個好方法可以做到這一點?最好沒有反射(雖然我想這沒關系),但肯定沒有涉及每種類型案例的反射(這是首先具有函數的意義)?forEachforEachStringforEachIntforEach我知道(尚未實現的)泛型提案將在這方面非常有效,但我想用現有的技術來做到這一點!package mainimport (    "fmt")type onEach func(x interface{})func printString(x interface{}) {    xx := x.(string)    fmt.Printf("x is a string '%s'\n", xx)}func printInt(x interface{}) {    xx := x.(int)    fmt.Printf("x is an int '%d'\n", xx)}func forEach(y interface{}, onEach onEach) {    // code to ensure y is a slice omitted    a := y.([]interface{}) // <-------- THIS LINE PANICS    for _, x := range a {        onEach(x)    }}func main() {    s := []string{"foo", "bar"}    i := []int{1, 2, 3}    forEach(s, printString)    forEach(i, printInt)}
查看完整描述

2 回答

?
烙印99

TA貢獻1829條經驗 獲得超13個贊

所以這里有一個使用反射的答案,我想這不會太難看。


package main


import (

    "fmt"

    "reflect"

)


type onEach func(x interface{})


func printString(x interface{}) {

    xx := x.(string)

    fmt.Printf("x is a string '%s'\n", xx)

}


func printInt(x interface{}) {

    xx := x.(int)

    fmt.Printf("x is an int '%d'\n", xx)

}


func forEach(y interface{}, onEach onEach) {

    // code to ensure y is a slice omitted

    v := reflect.ValueOf(y)

    for i := 0; i < v.Len(); i++ {

        onEach(v.Index(i).Interface())

    }

}


func main() {

    s := []string{"foo", "bar"}

    i := []int{1, 2, 3}

    forEach(s, printString)

    forEach(i, printInt)

}


查看完整回答
反對 回復 2022-08-01
?
波斯汪

TA貢獻1811條經驗 獲得超4個贊

使用反射包在任意類型的切片上編寫迭代函數:


// forEach calls f for each element of slice s.

// The function f must have a single argument with

// the same type as the slice's element type.

func forEach(s interface{}, f interface{}) {

    sv := reflect.ValueOf(s)

    fv := reflect.ValueOf(f)

    for i := 0; i < sv.Len(); i++ {

        fv.Call([]reflect.Value{sv.Index(i)})

    }

}

像這樣使用它:


func printString(s string) {

    fmt.Printf("x is a string %q\n", s)

}


s := []string{"foo", "bar"}

forEach(s, printString)

此答案與問題中的代碼和另一個答案不同,因為該函數不需要使用類型評估。f


查看完整回答
反對 回復 2022-08-01
  • 2 回答
  • 0 關注
  • 151 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號