作为Golang开发的小白,日常开发时候总会遇到一些问题,本篇博客的会收录一些日常开发时踩过的坑,可能有解决了的,也许也会有没解决的。
在使用for-range进行遍历切片或数组时,遍历时的指针index,value只是一个临时且地址不变的内存地址
package main
import "fmt"
func main() {
num := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
numPointer := [10]*int{}
for i, v := range num {
numPointer[i] = &v
fmt.Print(&i, " ") //0xc00001e0c8 0xc00001e0c8 0xc00001e0c8 0xc00001e0c8 0xc00001e0c8 0xc00001e0c8 0xc00001e0c8 0xc00001e0c8 0xc00001e0c8 0xc00001e0c8
}
fmt.Println(numPointer) //[0xc00001e0f0 0xc00001e0f0 0xc00001e0f0 0xc00001e0f0 0xc00001e0f0 0xc00001e0f0 0xc00001e0f0 0xc00001e0f0 0xc00001e0f0 0xc00001e0f0]
}
要想的到原来切片或者数组中元素的的地址应该改为
numPointer[i] = &num[i]
在进行函数调用时,应注意函数的参数与返回值是否冲突或者是否在相同调用区域内
package main
import (
"errors"
"fmt"
)
//test 将参数进行加1后与一个err,一起返回
func test(a int) (int, error) {
a++
return a, errors.New("test")
}
func main() {
var b int
for i := 0; i < 2; i++ {
b, err := test(b)
if err != nil {
fmt.Println(err, b)
}
}
fmt.Println(b)
}
输出结果为:
test 1
test 1
0
将main函数中的test调用改为:
func main() {
var b int
var err error
for i := 0; i < 2; i++ {
b, err = test(b)
if err != nil {
fmt.Println(err, b)
}
}
fmt.Println(b)
}
修改后输出为:
test 1
test 2
2
package main
import (
"fmt"
"strconv"
"time"
)
// 接口:一组方法的集合
// OpenCloser 接口定义两个方法 返回 error
type OpenCloser interface {
Open() error
Close() error
}
type win struct {
open bool // 门的状态是否开启
lock bool // 门的状态是否上锁
}
func (d *win) Open() error {
fmt.Println("win open...")
d.open = true
return nil
}
func (d *win) Close() error {
fmt.Println("win close...")
d.open = false
return nil
}
type Door struct {
win
open bool // 门的状态是否开启
lock bool // 门的状态是否上锁
}
func (d *Door) Open() error {
fmt.Println("door open...")
d.open = true
return nil
}
type AutoDoor struct {
OpenCloser // 匿名接口
delay int // 延迟多长时间开启
msg string // er自动开启时的警报
}
func (a *AutoDoor) Open() error {
fmt.Println("Open after " + strconv.Itoa(a.delay) + " seconds")
time.Sleep(time.Duration(a.delay) * time.Second)
fmt.Println("Door is opening:" + a.msg)
return nil
}
func main() {
//door := &AutoDoor{&Door{false, false}, 3, "warning"}
door:=&AutoDoor{
OpenCloser: &win{
open: false,
lock: false,
},
delay: 3,
msg: "test",
}
door.Open()//AutoDoor
if v, ok := door.OpenCloser.(*win); ok { //类型断言
fmt.Println("1",v)
}
door.OpenCloser.Open()//door
if v, ok := door.OpenCloser.(*Door); ok { //类型断言
fmt.Println("2",v)
}
door.Close()//win
if v, ok := door.OpenCloser.(*win); ok { //类型断言
fmt.Println("3",v)
}
fmt.Println("4",door.OpenCloser.(*Door))
}
输出结果为:
Open after 3 seconds
Door is opening:test
1 &{false false}
win open...
win close...
3 &{false false}
4 &{false false}
当结构中有匿名空接口时,注意创建新对象时传入的空接口为指针类型,否则会报错。
var _ interfaceName=new(typeName)
var _ interfaceName=(*typeName)(nil)
package main
import "fmt"
type a interface {
say(string) string
walk()
}
type b interface {
say(str string) string
}
type Person struct {
name string
}
func (p *Person) say(str string) string {
return p.name + " say " + str
}
var _ b = new(Person)//会分配内存,编译器检查,编译时检查
var _ b = (*Person)(nil)//不会分配内存,编译器检查,编译时检查
func main() {
person := &Person{name: "Alice"}
var i interface{} = person
c := i.(b)
fmt.Println(c.say("hello"))//Alice say hello
}
引申出new与make的区别