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

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

Go 生成器函數來創建滿足接口的值

Go 生成器函數來創建滿足接口的值

Go
牧羊人nacy 2022-06-27 15:41:40
我試圖概括一些代碼中的值類型。我需要制作一大堆值,然后對它們進行操作。API 大致如下:type Foo interface {  A(string) error}func Run(foo_gen func () (Foo, error)) {  ...}另一方面,我有:type bar struct {  ...}func (bar Bar) A (s string) {  ...}func main() {  foo_gen := func () (bar, error) {  return bar{}, nil  }  mypackage.Run(foo_gen)}這失敗并顯示錯誤消息:cannot use foo_gen (type func () (bar, error)) as type func() (mypackage.Foo, error) in argument to mypackage.Run我還很陌生,所以我可能缺少一些基本的東西。我所期待的是編譯器會嘗試通過匹配方法類型(類似于記錄子類型關系)顯式bar轉換為Foo,但情況似乎并非如此?
查看完整描述

2 回答

?
HUWWW

TA貢獻1874條經驗 獲得超12個贊

解釋可能令人驚訝,但實際上很簡單。

foo_gen被定義為func () (Foo, error),所以第一個返回值的類型Foo是 ,它是一個接口。

任何接口類型的值都是struct具有兩個指針的:指向該接口值中實際保存的具體值和指向(一些內部對象表示)它的類型。關于如何實現接口值的經典且非常好的(如果可能有點生疏)解釋是this。

您嘗試匹配我們剛剛討論的簽名的實際函數返回一個類型的值Bar作為它的第一個返回值。該類型是一種struct類型,它與原始簽名所期望的接口值無關。
換句話說,為了讓你的函數返回一個類型的值Bar滿足期望接口類型值的簽名,Foo編譯器必須生成代碼,將返回的值復制Bar到堆并從中合成一個值Foo。雖然可能是可行的,但這太含蓄了,否則可能會令人驚訝。

由于幾乎相同的原因,編譯器不允許將切片分配給[]T類型變量。[]interface{}


查看完整回答
反對 回復 2022-06-27
?
叮當貓咪

TA貢獻1776條經驗 獲得超12個贊

在類型級別上,這就是正在發生的事情。


問題是 go 編譯器無法將 a 提升func () (bar, error))到 afunc () (Foo, error)因為通常 go 值不是covariant。


這樣做的結果是有幾種方法可以解決這個問題。


一種是改變函數的返回類型:


foo_gen := func () (Foo, error) {

  return bar{}, nil

}

這是有效的,因為它能夠輕松地將bar{}值提升到一個Foo值。


如果我無法更改生成器函數(這也適用于通道等),另一種方法是將生成器包裝在另一個函數中:


bar_gen := func () (bar, error){

  return bar{}, nil

}

  

foo_gen := func() (Foo, error){

  foobar, err := bar_gen()

  return foobar, err

}


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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