Golang基础-9

Go语言基础

介绍

基础

介绍

  • 本文介绍Go语言中自定义类型、结构体定义、结构体声明、结构体初始化、字段访问与修改、匿名结构体、结构体嵌套、初始化函数定义等相关知识。

基础

结构体
  • 相对于其它的数据类型有唯一的类型,Go语言中提供结构体类型,结构体是由一个或多个任意类型的值聚合成的实体,每个值都是结构体的成员。
自定义类型
  • Go语言中使用 type 定义一种新的类型,也就是类型别名,由于Go语言中对数据类型检查比较严,认为是新类型,两个类型不能自动隐式转换,需要强制转换。
package main

import "fmt"

type MyInt int   // 将int重新自定义为新类型(起别名)

func main() {
	var a int = 10
	var b MyInt = 20
	fmt.Printf("a type: %T, value %v\n", a, a)
	fmt.Printf("b type: %T, value %v\n", b, b)

	// invalid operation: a == b (mismatched types int and MyInt)
	// fmt.Println("a == b: ", a == b)

	// 强制转换
	fmt.Println("a == b: ", a == int(b))
}

输出结果
a type: int, value 10
b type: main.MyInt, value 20
a == b: false

结构体定义
  • 结构体属于自定义数据类型、使用 struct 关键字声明,格式如下:

type 类型名 struct {
字段1 字段1类型
字段2 字段2类型

}

结构体声明
  • 将非指针变量声明为已经定义的结构体类型,默认初始化为哥字段对应的初始值。
  • 也可以使用指针直接声明结构体指针变量,此指针变量被初始化为 nil。
package main

import "fmt"

type Computer struct {
	id     int
	user   string
	update bool
}

func main() {
	var a Computer  // 声明结构体实例
	fmt.Printf("a type: %T, value: %v\n", a, a)
}

输出结果
a type: main.Computer, value: {0 false}

结构体初始化
  • 结构体创建的变量称为对应结构体的实例或者对象。Go语言中结构体有多种初始化方式,以下将详细说明。
  • 使用各类型默认值初始化。
package main

import "fmt"

type Computer struct {
	id     int      // 默认为0
	user   string   // 默认为空
	update bool     // 默认为false
}

func main() {
	var a Computer = Computer{}
	fmt.Printf("a type: %T, value: %v\n", a, a)
}

输出结果
a type: main.Computer, value: {0 false}

  • 使用字面量初始化。
package main

import "fmt"

type Computer struct {
	id     int
	user   string
	update bool
}

func main() {
	var a Computer = Computer{ // 所有字段初始化
		1001,
		"Admin",
		true, // 注意最后的类型末尾逗号不能省略
	}
	fmt.Printf("a type: %T, value: %v\n", a, a)

	// 初始化指定字段,未指定的字段使用各字段类型默认初始化值
	var b Computer = Computer{id: 1002, update: true}
	fmt.Printf("b type: %T, value: %v\n", b, b)

	// 分别初始化结构体字段值
	var c Computer
	c.id = 1003
	c.user = "root"
	fmt.Printf("c type: %T, value: %v\n", c, c)

	// 自动推导类型并初始化
	d := Computer{ // 必须所有字段初始化
		1004,
		"pin",
		true, // 注意最后的类型末尾逗号不能省略
	}
	fmt.Printf("d type: %T, value: %v\n", d, d)
}

输出结果
a type: main.Computer, value: {1001 Admin true}
b type: main.Computer, value: {1002 true}
c type: main.Computer, value: {1003 root false}
d type: main.Computer, value: {1004 pin true}

  • 初始化结构体指针。
package main

import "fmt"

type Computer struct {
	id     int
	user   string
	update bool
}

func main() {
	// 声明结构体指针,未初始化,默认指向nil
	var a *Computer
	fmt.Printf("a type: %T, value: %v\n", a, a)

	// 使用 new 实例化结构体指针,默认初始化
	var b *Computer = new(Computer)
	fmt.Printf("b type: %T, value: %v\n", b, b)
	b.id = 1005 
	b.user = "pwd"
	fmt.Printf("init b type: %T, value: %v\n", b, b)

	// 取地址实例化
	c := &Computer{
		1006,
		"ccc",
		true,
	}
	fmt.Printf("c type: %T, value: %v\n", c, c)
}

输出结果
a type: *main.Computer, value:
b type: *main.Computer, value: &{0 false}
init b type: *main.Computer, value: &{1005 pwd false}
c type: *main.Computer, value: &{1006 ccc true}

字段访问与修改
package main

import "fmt"

type Computer struct {
	id     int
	user   string
	update bool
}

func main() {
	// 声明并初始化普通变量
	var v Computer = Computer{id: 1007, update: true}
	// 访问结构体字段
	fmt.Println("read v: id = ", v.id, ", user = ", v.user, ", update = ", v.update)
	// 修改结构体字段
	v.id = 1008
	fmt.Println("modify v: id = ", v.id, ", user = ", v.user, ", update = ", v.update)

	// 使用取地址实例化结构体指针
	c := &Computer{
		1009,
		"ccc",
		true,
	}
	// 访问结构体字段
	fmt.Println("read c: id = ", c.id, ", user = ", c.user, ", update = ", c.update)

	// 修改结构体字段
	// 对于结构体指针,修改字段时这两种写法均可
	c.id = 1010 // 会自动转换为 (*c).id = 1010
	(*c).user = "pwd"
	fmt.Println("modify c: id = ", c.id, ", user = ", c.user, ", update = ", c.update)
}

输出结果
read v: id = 1007 , user = , update = true
modify v: id = 1008 , user = , update = true
read c: id = 1009 , user = ccc , update = true
modify c: id = 1010 , user = pwd , update = true

匿名结构体
  • 在使用时直接使用 struct 关键字定于并初始化结构体变量或结构体指针变量,简单理解就是结构体没有指定名称,所以称之为匿名结构体。
package main

import (
	"fmt"
	"reflect"
)

func main() {
	// 匿名结构体变量
	addr := struct {
		ip   string
		port int
	}{"127.0.0.1", 9999}

	fmt.Println("net addr: ", addr, ", type: ", reflect.TypeOf(addr))

	// 匿名结构体指针变量
	addr2 := &struct {
		ip   string
		port int
	}{"127.0.0.1", 8080}
	fmt.Println("net addr2: ", addr2, ", type: ", reflect.TypeOf(addr2))

	// 匿名结构体数组
	addr3 := [...]struct {
		ip   string
		port int
	}{{"127.0.0.1", 1111}, {"127.0.0.1", 2222}, {"127.0.0.1", 3333}}
	fmt.Println("net addr3: ", addr3, ", type: ", reflect.TypeOf(addr3))

	// 匿名结构体切片
	addr4 := []struct {
		ip   string
		port int
	}{{"127.0.0.1", 4444}, {"127.0.0.1", 5555}}
	fmt.Println("net addr4: ", addr4, ", type: ", reflect.TypeOf(addr4))
}

输出结果
net addr: {127.0.0.1 9999} , type: struct { ip string; port int }
net addr2: &{127.0.0.1 8080} , type: *struct { ip string; port int }
net addr3: [{127.0.0.1 1111} {127.0.0.1 2222} {127.0.0.1 3333}] , type: [3]struct { ip string; port int }
net addr4: [{127.0.0.1 4444} {127.0.0.1 5555}] , type: []struct { ip string; port int }

结构体嵌套
  • 结构体也可以嵌套,这对于抽象出的公共数据多次复用非常易用。
  • 嵌套分为命名嵌套和匿名嵌套。不能嵌套两个相同名称的结构体。
  • 在不同的结构体中有相同名称的字段时,不能使用匿名嵌套。
package main

import "fmt"

type Base struct {
	name string
	id   int
}

// 定义结构体命名嵌套
type Cpu struct {
	cpuType int
	base    Base
}

// 定义结构体匿名嵌套
type Memory struct {
	mem int
	Base
}

// 定义结构体命名嵌套指针
type Net struct {
	chose int
	base  *Base
}

// 定义结构体匿名嵌套指针
type View struct {
	color int
	*Base
}

func PointerStructVar() {
	// 命名嵌套结构体指针声明并初始化所有变量
	a := Net{1, &Base{"NNN", 10000}}
	fmt.Println("a: ", a)
	fmt.Printf("a.chose=%v, a.name=%v, a.id=%v\n", a.chose, a.base.name, a.base.id)
	// 命名嵌套结构体指针指定字段初始化
	b := Net{chose: 2, base: &Base{"NNNNNN", 20000}}
	fmt.Println("b: ", b)
	fmt.Printf("b.chose=%v, b.name=%v, b.id=%v\n", b.chose, b.base.name, b.base.id)

	// 命名嵌套结构体指针修改字段
	a.base.id = 10001
	(*a.base).name = "NNM"
	fmt.Println("modify a: ", a)
	fmt.Printf("a.chose=%v, a.name=%v, a.id=%v\n", a.chose, a.base.name, a.base.id)

	// 匿名嵌套结构体指针声明并初始化所有变量
	aa := View{100, &Base{"XXX", 10000}}
	fmt.Println("aa: ", aa)
	fmt.Printf("aa.color=%v, aa.name=%v, aa.id=%v\n", aa.color, aa.name, aa.id)
	// 匿名嵌套结构体指针指定字段初始化
	bb := View{color: 200, Base: &Base{name: "XXXXXX", id: 20000}}
	fmt.Println("bb: ", bb)
	fmt.Printf("bb.color=%v, bb.name=%v, bb.id=%v\n", bb.color, bb.name, bb.id)

	// 匿名嵌套结构体指针修改字段
	aa.id = 10001
	fmt.Println("modify aa: ", aa)
	fmt.Printf("aa.color=%v, aa.name=%v, aa.id=%v\n", aa.color, aa.name, aa.id)

}

func NormalStructVar() {
	// 命名嵌套结构体声明并初始化所有变量
	a := Cpu{1, Base{"intel", 10000}}
	fmt.Println("a: ", a)
	// 命名嵌套结构体指定字段初始化
	b := Cpu{cpuType: 2, base: Base{"AMD", 20000}}
	fmt.Println("b: ", b)

	// 命名嵌套结构体修改字段
	a.base.id = 10001
	fmt.Println("modify a: ", a)

	// 匿名嵌套结构体声明并初始化所有变量
	aa := Memory{100, Base{"DDR333", 10000}}
	fmt.Println("aa: ", aa)
	// 匿名嵌套结构体指定字段初始化
	bb := Memory{mem: 200, Base: Base{name: "DDR400", id: 20000}}
	fmt.Println("bb: ", bb)
	// 匿名嵌套结构体修改字段
	aa.id = 10001
	fmt.Println("modify aa: ", aa)
}

func main() {
	// 结构体变量操作
	NormalStructVar()
	fmt.Println("==================================")
	// 结构体指针变量操作
	PointerStructVar()
}

输出结果
a: {1 {intel 10000}}
b: {2 {AMD 20000}}
modify a: {1 {intel 10001}}
aa: {100 {DDR333 10000}}
bb: {200 {DDR400 20000}}
modify aa: {100 {DDR333 10001}}
==================================
a: {1 0xc000008048}
a.chose=1, a.name=NNN, a.id=10000
b: {2 0xc000008060}
b.chose=2, b.name=NNNNNN, b.id=20000
modify a: {1 0xc000008048}
a.chose=1, a.name=NNM, a.id=10001
aa: {100 0xc000008078}
aa.color=100, aa.name=XXX, aa.id=10000
bb: {200 0xc000008090}
bb.color=200, bb.name=XXXXXX, bb.id=20000
modify aa: {100 0xc000008078}
aa.color=100, aa.name=XXX, aa.id=10001

初始化函数定义
  • 在Go语言中,通常定义一个或多个New函数用于创建结构体实例。
package main

import "fmt"

type Base struct {
	name string
	id   int
}

func NewBase(name string, id int) *Base {
	return &Base{name, id}
}

func NewName(nm string) *Base {
	return &Base{name: nm}
}

func NewId(num int) *Base {
	return &Base{id: num}
}

func main() {
	a := NewBase("QWER", 100)
	fmt.Println("a: ", a)
}

输出结果
a: &{QWER 100}

起始

相关推荐

  1. Golang基础-9

    2024-04-08 09:14:02       16 阅读
  2. Golang基础教程

    2024-04-08 09:14:02       42 阅读
  3. 指针基础 - golang

    2024-04-08 09:14:02       21 阅读
  4. Golang基础-5

    2024-04-08 09:14:02       18 阅读
  5. Golang基础-4

    2024-04-08 09:14:02       16 阅读
  6. Golang基础-3

    2024-04-08 09:14:02       17 阅读
  7. Golang基础-6

    2024-04-08 09:14:02       16 阅读
  8. Golang基础-7

    2024-04-08 09:14:02       16 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-08 09:14:02       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-08 09:14:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-08 09:14:02       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-08 09:14:02       20 阅读

热门阅读

  1. spring介绍

    2024-04-08 09:14:02       17 阅读
  2. 鼎盛合方案设计——汽车轮胎气压监测方案

    2024-04-08 09:14:02       15 阅读
  3. 全球化业务的网络安全挑战

    2024-04-08 09:14:02       16 阅读
  4. gcc/g++:预编译阶段查看模块生成目标的直接依赖

    2024-04-08 09:14:02       15 阅读
  5. 【c++20】金山云liuguang引擎

    2024-04-08 09:14:02       14 阅读
  6. MongoDB数据库服务

    2024-04-08 09:14:02       15 阅读
  7. 每日一题:三数之和

    2024-04-08 09:14:02       15 阅读
  8. [AIGC] Spring Interceptor 的执行顺序是怎样的?

    2024-04-08 09:14:02       14 阅读