方法表達(dá)式

我在看 exec 包的時(shí)候發(fā)現(xiàn) cmd 在 start 的時(shí)候有這樣的一段代碼

...
    type F func(*Cmd) (*os.File, error)
    for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
        fd, err := setupFd(c)
        if err != nil {
            c.closeDescriptors(c.closeAfterStart)
            c.closeDescriptors(c.closeAfterWait)
            return err
        }
        c.childFiles = append(c.childFiles, fd)
    }
...

這樣一段代碼到底是什么意思,源碼中 stdin,stdout,stderr 是 *Cmd 作為 receiver 的幾個(gè)方法,是方法而不是函數(shù)。但是 F 其實(shí)是一個(gè)函數(shù),他沒(méi)有接受者,但是函數(shù)第一個(gè)參數(shù)也就是 receiver。

方法和函數(shù)的區(qū)別在于有沒(méi)有 receiver

所以做如下實(shí)驗(yàn)。。。

type People struct{}

func (p *People) sing() {
    fmt.Println("sing")
}

func (p *People) jump() {
    fmt.Println("jump")
}

func (p *People) rpa() {
    fmt.Println("rpa")
}

func (p *People) basketball() {
    fmt.Println("basketball")
}

// 方法表達(dá)式
func TestMethodFuc(t *testing.T) {
    var p People
    type F func(people *People)
    for _, f := range []F{(*People).sing, (*People).jump, (*People).rpa, (*People).basketball} {
        f(&p)
    }
}

通過(guò)這種方式可以很簡(jiǎn)單去調(diào)用一個(gè)結(jié)構(gòu)體下同一類(lèi)型的方法,否則代碼會(huì)寫(xiě)成這樣

func TestMethodFuc2(t *testing.T) {
    var p People

    p.sing()
    p.jump()
    p.rpa()
    p.basketball()
}

雖然更清晰了,但是考慮一下處理 error 會(huì)發(fā)現(xiàn) TestMethodFuc2 及其啰嗦。


type People struct{}

func (p *People) sing() error {
    fmt.Println("sing")
    return nil
}

func (p *People) jump() error {
    fmt.Println("jump")
    return nil
}

func (p *People) rpa() error {
    fmt.Println("rpa")
    return nil
}

func (p *People) basketball() error {
    fmt.Println("basketball")
    return nil
}

// 方法表達(dá)式
func TestMethodFuc1(t *testing.T) {
    var p People
    type F func(people *People) error
    for _, f := range []F{(*People).sing, (*People).jump, (*People).rpa, (*People).basketball} {
        if err := f(&p); err != nil {
            t.Fatal(err)
        }
    }
}

func TestMethodFuc2(t *testing.T) {
    var p People
    if err := p.sing(); err != nil {
        t.Fatal(err)
    }

    if err := p.jump(); err != nil {
        t.Fatal(err)
    }

    if err := p.rpa(); err != nil {
        t.Fatal(err)
    }

    if err := p.basketball(); err != nil {
        t.Fatal(err)
    }
}

明顯上面的處理方式更為簡(jiǎn)單清晰,sdk 的代碼確實(shí)很優(yōu)秀,需要斟酌思考。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容