You can hit this bug without using reflect. It, to me, is Go's third biggest wart. I'm particularly fond of this bug, because I got bit by it and it crashed prod during an important sales demo.
package main
type Compressor interface {
compress() []byte
}
type GZipComprosser struct {
internal byte
}
func (c *GZipComprosser) compress() []byte {
return []byte{c.internal}
}
func DoCompress(c Compressor) []byte {
if c == nil {
return []byte{}
}
return c.compress()
}
func main() {
var c *GZipComprosser
c = nil
DoCompress(c)
}
This is the "nil interface" trap and will crash with an NPE even though are "checking" nil.> It, to me, is Go's third biggest wart.
Out of curiosity, what are the first two?
Lack of generics and clumsy error handling would be my guess.
One of them has to be the for loop reusing value thing.
func processItem(item *string) {
if item == nil {
fmt.Println("nil item")
return
}
fmt.Println(*item)
}
stuffToProcess := []string{"one", "two"}
wg := sync.WaitGroup{}
for _, item := range stuffToProcess {
wg.Add(1)
go func(s *string) {
time.Sleep(1 * time.Millisecond)
processItem(s)
wg.Done()
}(&item)
}
wg.Wait()
// What do I print?
Playground here: https://play.golang.org/p/mouvT1BkpNJgosec[1] will warn you about this, at least.
[reuse.go:26] - G601 (CWE-118): Implicit memory aliasing in for loop. (Confidence: MEDIUM, Severity: MEDIUM)
25: wg.Done()
> 26: }(&item)
27: }
[1] https://github.com/securego/gosec