Skip to content

Commit

Permalink
Merge pull request #57 from tsingbx/interface-values
Browse files Browse the repository at this point in the history
add doc for interface values
  • Loading branch information
xushiwei authored Nov 7, 2023
2 parents 309c1f7 + bf8f09b commit 14635fe
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 1 deletion.
38 changes: 38 additions & 0 deletions 217-Interface-Values/interface-values-1.gop
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// The value of the interface type and the interface value are two different concepts.

// Go+ is a statically typed programming language, types are a compile time concept, so a type is not a value.
// The value of the type descriptor provides information about each type, such as its name and methods.
// In an interface value, the type component is represented by the appropriate type descriptor.

// In Go+, interfaces variables are always initialize well-defined value as other type variables.
// The zero value for an interface has both its type and value components set to nil, for example:

import (
"bytes"
"io"
"os"
)

var w io.Writer

println w == nil

var w2 io.Writer = os.Stdout

w2 = nil // same as w, both w and w2 interface variable has zero value

println w2 == nil

var r *bytes.Reader

println r == nil

var r2 io.Reader = r // r2 has non-zero interface value. Its dynamic type is *bytes.Reader and its dynamic value is nil. So the result of r2 == nil is false

if r2 != nil {
slice := []byte{}
r2.Read(slice) // panic: runtime error: invalid memory address or nil pointer dereference
}

// The interface variable w has zero value. So both its dynamic type and its dynamic value are nil. In this case, the result of if w == nil is true.
// The interface variable r2 has non-zero value. Its dynamic type is *bytes.Reader and its dynamic value is nil. So the result of r2 == nil is false.
19 changes: 19 additions & 0 deletions 217-Interface-Values/interface-values-2.gop
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Interface values may be compared using == and !=. Two interface values are equal if both are
// nil, or if their dynamic types are identical and their dynamic values are equal according to the
// usual behavior of == for that type. Because interface values are comparable, they may be used
// as the keys of a map or as the operand of a switch statement.

// However, if two interface values are compared and have the same dynamic type, but that type
// is not comparable (a slice, for instance), then the comparison fails with a panic. For example

var x = []any{1, 2, 3}
var y = []any{1, 2, 3}

println(x == y) // panic: comparing uncomparable type []int

// In this respect, interface types are unusual. Other types are either safely comparable (like
// basic types and pointers) or not comparable at all (like slices, maps, and functions), but when
// comparing interface values or aggregate types that contain interface values, we must be aware
// of the potential for a panic. A similar risk exists when using interfaces as map keys or switch
// operands. Only compare interface values if you are certain that they contain dynamic values
// of comparable types.
21 changes: 21 additions & 0 deletions 217-Interface-Values/interface-values-3.gop
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// When handling errors, or during debugging, it is often helpful to report the dynamic type of
// an interface value. For that, we use the fmt package’s %T verb:

import (
"bytes"
"fmt"
"io"
"os"
)

var w io.Writer

fmt.printf "%T\n", w // "<nil>"

w = os.Stdout
fmt.printf "%T\n", w // "*os.File"

w = new(bytes.Buffer)
fmt.printf "%T\n", w // "*bytes.Buffer"

// Internally, fmt uses reflection to obtain the name of the int erface’s dynamic type.
1 change: 0 additions & 1 deletion 217-Interface-Values/interface-values.gop

This file was deleted.

0 comments on commit 14635fe

Please sign in to comment.