RosettaCodeData/Task/Undefined-values/Go/undefined-values.go

98 lines
1.7 KiB
Go

package main
import "fmt"
var (
s []int
p *int
f func()
i interface{}
m map[int]int
c chan int
)
func main() {
fmt.Println("Exercise nil objects:")
status()
// initialize objects
s = make([]int, 1)
p = &s[0] // yes, reference element of slice just created
f = func() { fmt.Println("function call") }
i = user(0) // see user defined type just below
m = make(map[int]int)
c = make(chan int, 1)
fmt.Println("\nExercise objects after initialization:")
status()
}
type user int
func (user) m() {
fmt.Println("method call")
}
func status() {
trySlice()
tryPointer()
tryFunction()
tryInterface()
tryMap()
tryChannel()
}
func reportPanic() {
if x := recover(); x != nil {
fmt.Println("panic:", x)
}
}
func trySlice() {
defer reportPanic()
fmt.Println("s[0] =", s[0])
}
func tryPointer() {
defer reportPanic()
fmt.Println("*p =", *p)
}
func tryFunction() {
defer reportPanic()
f()
}
func tryInterface() {
defer reportPanic()
// normally the nil identifier accesses a nil value for one of
// six predefined types. In a type switch however, nil can be used
// as a type. In this case, it matches the nil interface.
switch i.(type) {
case nil:
fmt.Println("i is nil interface")
case interface {
m()
}:
fmt.Println("i has method m")
}
// assert type with method and then call method
i.(interface {
m()
}).m()
}
func tryMap() {
defer reportPanic()
m[0] = 0
fmt.Println("m[0] =", m[0])
}
func tryChannel() {
defer reportPanic()
close(c)
fmt.Println("channel closed")
}