Benchmark jasne ukazuje ze pouzivat pointer metody je 2x pomalsie nez pouzivat value metody. To je v pohode lebo sa to da lahko odlisit podla toho ci ide o mutacnu metodu alebo nie. Ale rozmyslal som o navratovych hodnotach. Casto sa totiz robia funkcie na styl
func Foo() (*Bar, error) {}
Tam je totozna situacia ze pointer je 2x narocnejsi na spracovanie(heap vs stack).
Testovanie mi ukazalo ze penalizacia zalezi od toho co sa s navratovou hodnotou robi(escape analyza go runtime), primarne ako daleko hodnota cestuje. V kazdom pripade som rozmyslal ze co keby navratova hodnota vyzerala takto:
type Foo struct {
err string
Bar int
Baz string
}
func (f Foo) Error() {
return f.err
}
func DoStuff() Foo {
if failed {
return Foo{err: "chyba"}
}
return Foo{Bar: 10, Baz: "ok"}
}
func main() {
result := DoStuff()
if result.Error() != "" {
log.Fatal(result.Error())
}
log.Println("all good")
}
Cize Foo matchne error interfejs ale ako hodnota, nie ako pointer a teda namiesto dvoch pointerov (return *Foo, error) je len jedna hodnota Foo ktora vie predat informaciu ci error bol alebo ci je vysledok ok a moze sa s nim pracovat dalej.
To len tak teoreticky premyslam na hlas, ci sa oplati optimalizovat kod takto alebo ani nie... napriklad pri vytazenom http serveri ktory riesi miliony requestov denne by to mohlo pridat par percent na vykone. Problem je ze to by cela codebase musela byt takto prerobena. Dalsi problem je, v pripade http serveru, ze v pripade serializacie(json, xml, yaml,...) by nefungovali omitempty tagy co je dost velky problem kedze sa tym straca informacia o data present vs data not-present.
Diskutovat o pointer vs value v go je taka zaciatocnicka otazka ktoru myslim riesia vseci novoprichodilci ale casom proste pouzivaju aj tak pointery lebo je to standard v 99% pripadoch. Ale teraz po rokoch nad tym rozmyslam znovu, ci to ma vyznam sa tym zaoberat alebo nie.