first commit
commit
12dfd884d8
|
@ -0,0 +1,2 @@
|
||||||
|
.idea/
|
||||||
|
.gitignore
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Go 踩坑记
|
||||||
|
|
||||||
|
笔记在 [语雀](https://www.yuque.com/g/dugulingping/fyq6sq/qvn5s8ozqmvkbs17/collaborator/join?token=fDDbYcq9q59hVTd9) 中
|
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// 如题,map和slice是引用类型还是值类型
|
||||||
|
func main() {
|
||||||
|
// slice
|
||||||
|
s := []int{1, 2, 3}
|
||||||
|
testSlice(s)
|
||||||
|
fmt.Println(s) // [100 2 3]
|
||||||
|
|
||||||
|
// map
|
||||||
|
m := map[string]int{"test": 1}
|
||||||
|
testMap(m)
|
||||||
|
fmt.Println(m) // map[test:100]
|
||||||
|
// 结论:map和slice都是引用类型
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写一个函数,传入一个slice,修改slice的值,看看是否会影响到原来的slice
|
||||||
|
func testSlice(s []int) {
|
||||||
|
s[0] = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写一个函数,传入一个map,修改map的值,看看是否会影响到原来的map
|
||||||
|
func testMap(m map[string]int) {
|
||||||
|
m["test"] = 100
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// 先来看个例子
|
||||||
|
var num *int
|
||||||
|
var a interface{}
|
||||||
|
|
||||||
|
fmt.Println(num == nil) // true
|
||||||
|
fmt.Println(a == nil) // true
|
||||||
|
fmt.Println(a == num) // false
|
||||||
|
|
||||||
|
// 我将会用(Type, Value)来表示一个变量完整的类型和值
|
||||||
|
fmt.Printf("num:(%T, %[1]v)\n", num) // num:(*int <nil>)
|
||||||
|
fmt.Printf("a:(%T, %[1]v)\n", a) // a:(<nil>, <nil>)
|
||||||
|
|
||||||
|
fmt.Println(num == nil) // (*int, nil) == (*int, nil) // true
|
||||||
|
fmt.Println(a == nil) // (<nil>, <nil>) == (<nil>, <nil>) // true
|
||||||
|
fmt.Println(a == num) // (<nil>, <nil>) == (*int, nil) // false
|
||||||
|
|
||||||
|
// 从上面的例子可以看出,interface{}类型的值和nil比较时,会先判断类型是否相同,如果类型相同,再判断值是否相同
|
||||||
|
|
||||||
|
// 再来看个例子
|
||||||
|
var num2 *int = nil
|
||||||
|
var b interface{} = num2 // 在这里,b的动态类型已经是(*int, nil)
|
||||||
|
fmt.Println(b == nil) // (<*int>, <nil>) == (<nil>, <nil>) // false
|
||||||
|
fmt.Println(num2 == nil) // (<*int>, <nil>) == (<*int>, <nil>) // true
|
||||||
|
fmt.Println(b == num2) // (<*int>, <nil>) == (<*int>, <nil>) // true
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
data := []byte{1, 2, 3}
|
||||||
|
// Badwriter(-1) 返回的是一个接口类型, 它的动态类型是(*strings.Builder, nil)
|
||||||
|
// write 方法的参数是一个 io.Writer 类型的值, 所以实际上是是一个接口类型
|
||||||
|
// w接受的到的动态类型是(*strings.Builder, nil)
|
||||||
|
// 因为 (*strings.Builder, nil) 和 (nil, nil) 是不同的类型, 所以这里w != nil 为 true
|
||||||
|
// 又因为空指针不可以调用方法, 所以这里会报错
|
||||||
|
w := BadWriter(-1)
|
||||||
|
fmt.Printf("w:(%T, %[1]v)\n", w) // w:(io.Writer, <nil>)
|
||||||
|
if w != nil {
|
||||||
|
w.Write(data)
|
||||||
|
} else {
|
||||||
|
println("w is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Badwriter 接受一个 int 类型的参数,返回一个 io.Writer 类型的值
|
||||||
|
// 如果 n > 0,返回一个 *strings.Builder 类型的值
|
||||||
|
// 如果 n <= 0,返回 nil
|
||||||
|
func BadWriter(n int) io.Writer {
|
||||||
|
// strings.Builder 是一个结构体, 它实现了 io.Writer 接口
|
||||||
|
var b *strings.Builder = nil
|
||||||
|
// 看看 b 的类型
|
||||||
|
fmt.Printf("b:(%T, %[1]v)\n", b) // b:(*strings.Builder, <nil>)
|
||||||
|
if n > 0 {
|
||||||
|
b = &strings.Builder{}
|
||||||
|
}
|
||||||
|
// 当n不合法是, 返回的实际上是一个接口类型, 它的动态类型是(*strings.Builder, nil)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func goodWriter(n int) io.Writer {
|
||||||
|
if n > 0 {
|
||||||
|
return &strings.Builder{}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type err string
|
||||||
|
|
||||||
|
func (err err) Error() string {
|
||||||
|
return string(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const EOF = err("EOF")
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
reader := bytes.NewBuffer([]byte{1, 2, 3})
|
||||||
|
result, err := io.ReadAll(reader)
|
||||||
|
fmt.Println(result, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
io.EOF = EOF
|
||||||
|
}
|
Loading…
Reference in New Issue