Go语言中一些类似但不同语法等使用的区别

数组、new

1. &{}和new()

banker := &Banker{}
banker := new(Banker) 两者的区别

&Banker{}new(Banker) 都是用来创建一个指向 Banker 类型的指针

  1. 使用 &Banker{}:
    • 这是使用复合字面量(composite literal)来创建一个 Banker 结构体,并取其地址。
    • 它允许你在创建结构体的同时初始化结构体的字段。如果你不提供任何字段值,那么所有字段都会被设置为零值。
    • 示例:banker := &Banker{Field1: value1, Field2: value2} 允许你直接指定某些字段的初始值。
  2. 使用 new(Banker):
    • 这是使用内置的 new 函数来分配内存。它返回一个指向新分配的零值 Banker 结构体的指针
    • 该函数只分配内存不允许你同时初始化字段;所有的字段都将被设置为其类型的零值。
    • 示例:banker := new(Banker) 只会给你一个所有字段都是零值的 Banker 结构体的指针。

在大多数情况下,两者可以互换使用。


2. go build 和 run

  1. 输出
    • go build 会生成一个可执行文件,但不会自动运行它。
    • go run 不会生成持久的可执行文件,而是编译后立即运行,并且通常不会保留生成的临时文件。
  2. 用途
    • go build 适用于正式构建应用,尤其是当你需要分发可执行文件时。
    • go run 适用于快速测试和开发,因为你可以直接看到结果而无需担心清理生成的文件。
  3. 性能
    • go build 通常用于生产环境,因为它只进行一次编译,之后可以多次运行生成的可执行文件。
    • go run 每次都需要重新编译源代码,因此在频繁运行同一段代码时可能会显得较慢。
  4. 调试
    • 使用 go build 生成的可执行文件可以更方便地使用外部调试工具。
    • go run 更适合快速迭代和测试,尤其是在不需要复杂调试的情况下。

3. “继承”和”组合”

CatCCatB 两种结构体虽然都包含 Cat 类型,但它们的包含方式不同,这导致了它们在使用和行为上的差异。

type Cat struct {}    
type CatC struct {
C *Cat
}
type CatB struct {
Cat
}

CatC 结构体(组合)

type CatC struct {
C *Cat
}
  • 字段类型CatC 包含一个指向 Cat 的指针 C
  • 内存布局CatC 只包含一个指针,这个指针指向 Cat 实例的内存地址。因此,CatC 本身只占用指针的大小(通常是 8 字节,在 64 位系统上)。
  • 初始化:需要显式地创建 Cat 实例并将其指针赋值给 C
  • 访问成员:通过 CatC 访问 Cat 的成员时,需要通过指针解引用,例如 catCInstance.C.Member

CatB 结构体(继承)

type CatB struct {
Cat
}
  • 字段类型CatB 包含一个 Cat 类型的匿名字段。
  • 内存布局CatB 直接包含 Cat 的所有字段。因此,CatB 的大小是 Cat 的大小。
  • 初始化:可以直接初始化 CatB,而不需要显式地创建 Cat 实例。
  • 访问成员:可以通过 CatB 直接访问 Cat 的成员,例如 catBInstance.Member。此外,由于 Cat 是匿名字段,你也可以直接访问 Cat 的方法。

代码示例:

package main

import "fmt"

type Cat struct {}

func (c *Cat) Eat() {
fmt.Println("小猫吃饭")
}

//给小猫添加一个 可以睡觉的方法 (使用继承来实现)
type CatB struct {
Cat
}

func (cb *CatB) Sleep() {
fmt.Println("小猫睡觉")
}

//给小猫添加一个 可以睡觉的方法 (使用组合的方式)
type CatC struct {
C *Cat
}

func (cc *CatC) Sleep() {
fmt.Println("小猫睡觉")
}


func main() {
//通过继承增加的功能,可以正常使用
cb := new(CatB)
cb.Eat() //继承可以直接调用(隐式)--调用Cat的方式不同 -1
cb.Sleep()

//通过组合增加的功能,可以正常使用
cc := new(CatC)
cc.C = new(Cat)
cc.C.Eat() //组合需要显示调用(显式) -1
cc.Sleep()
}