2 回答

TA貢獻(xiàn)1765條經(jīng)驗(yàn) 獲得超5個(gè)贊
去 1.18
您可以使用通用函數(shù)來捕獲切片的基本類型并返回長(zhǎng)度為零的切片:
func echo[T any](v []T) []T {
return make([]T, 0)
}
func main() {
n := foo.GetFooBar()
if n == nil {
n = echo(n) // no need to refer to apiv17 here
}
bytes, _ := json.Marshal(n)
fmt.Println(string(bytes)) // prints []
}
需要常規(guī)參數(shù)v []Tin的目的echo是允許類型推斷將切片[]apiv17.SomeObject與參數(shù)統(tǒng)一[]T并推斷T為基本類型apiv17.SomeObject,這樣您就可以調(diào)用它,echo(n)而無需顯式類型參數(shù)。
該包apiv17當(dāng)然在編譯時(shí)是已知的,因?yàn)樗峭ㄟ^ 傳遞導(dǎo)入的myPackage,因此您可以利用這一點(diǎn)和類型推斷來避免為 . 添加顯式import語句apiv17。
這就是它在多文件游樂場(chǎng)上的樣子:https ://go.dev/play/p/4ycTkaGLFpo
該類型在bar包中聲明,但main僅導(dǎo)入play.ground/foo且僅使用foo.GetFooBar.
轉(zhuǎn)到 1.17 及以下版本
反射。只需將echo上面的函數(shù)更改為接受interface{}參數(shù)(anyGo 1.17 中沒有,還記得嗎?),然后執(zhí)行以下操作reflect.MakeSlice:
func set(v interface{}) {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
panic("not a ptr")
}
reflect.Indirect(rv).Set(reflect.MakeSlice(rv.Type().Elem(), 0, 0))
}
然后傳遞一個(gè)指向切片的指針,這樣你就可以用反射來設(shè)置它的值。
func main() {
n := foo.GetFooBar()
if n == nil {
set(&n)
}
fmt.Printf("type: %T, val: %v, is nil: %t\n", n, n, n == nil)
// type: []bar.FooBar, val: [], is nil: false
bytes, _ := json.Marshal(n)
fmt.Println(string(bytes)) // prints [] again
}
Go 1.17 游樂場(chǎng):https ://go.dev/play/p/4jMkr22LMF7?v=goprev

TA貢獻(xiàn)1864條經(jīng)驗(yàn) 獲得超2個(gè)贊
另一個(gè)答案描述了如何創(chuàng)建一個(gè)空切片。
但是你可以更簡(jiǎn)單地解決你原來的問題:如果results是nil,你不需要?jiǎng)?chuàng)建一個(gè)空切片,不管它有什么元素類型,[]無論如何 JSON 封送處理都是。因此,如果results是nil,則無需調(diào)用json.Marshal(),只需“輸出”即可[]:
results, err := myLibrary.Search()
var bytes []byte
if results == nil {
bytes = []byte{'[', ']' } // JSON marshaling result is "[]"
} else {
bytes, err = json.Marshal(results)
// Handle error
}
- 2 回答
- 0 關(guān)注
- 105 瀏覽
添加回答
舉報(bào)