Golang Struct 示例教程

Golang Struct 示例教程

结构体是包括一组属性或字段的用户定义类型。,用来组织相关数据为一个整体。结构体可以描述现实世界实体的一组属性。
如果你有面向对象编程背景,可以认为结构体是轻量级的类,支持组合但不支持继承。

1. 定义结构体类型

下面定义新的结构体:

type Person struct {
	FirstName string
	LastName  string
	Age       int
}

type关键词定义新的类型,接着是用户类型名称,后面关键字struct表明正在定义结构体。结构体的花括号内包括一组属性,每个属性有名称和类型。

注,相同类型可以合并:

type Person struct {
	FirstName, LastName string
	Age       int
}

2. 声明并初始化结构体

2.1 声明结构体变量

和其他数据类型一样,可以声明struct类型变量:

// 定义 'Person' 类型变量
var p Person // 所有属性为默认值

上面代码创建Person类型变量,变量默认值为零值。对结构体来说零值就是所有属性都保持各自类型零值。因此,字符串属性为“”,Age为0

2.2 初始化结构体

也可以定义结构体变量时初始化:

var p = Person{"New", "Sing", 26}

注意,属性值需要按照一定顺序,且不能是部分字段值,错误如下:

var p = Person{"Rajeev"} // Compiler Error: too few values in struct initializer

2.3 命名字段初始化结构体

Go支持以键值对方式初始化结构体,是否按照顺序不重要:

var p = Person{FirstName: "Rajeev", LastName: "Singh", Age: 25}

我们可以以多行方式指定属性值增强可读性(此时必须有结尾的逗号):

var p = Person{
	FirstName: "John",
	LastName:  "Snow",
	Age:       45,
}

键值对方式初始化支持仅初始化部分字段,所有未初始化的字段值为零值:

var p = Person{FirstName: "Alien"} // LastName: "", Age: 0
var p = Person{} // FirstName: "", LastName: "", Age: 0

2.4 完整示例

package main

import (
	"fmt"
)

// Defining a struct type
type Person struct {
	FirstName string
	LastName  string
	Age       int
}

func main() {
	// Declaring a variable of a `struct` type
	var p Person // // All the struct fields are initialized with their zero value
	fmt.Println(p)

	// Declaring and initializing a struct using a struct literal
	p1 := Person{"Rajeev", "Singh", 26}
	fmt.Println("Person1: ", p1)

	// Naming fields while initializing a struct
	p2 := Person{
		FirstName: "John",
		LastName:  "Snow",
		Age:       45,
	}
	fmt.Println("Person2: ", p2)

	// Uninitialized fields are set to their corresponding zero-value
	p3 := Person{FirstName: "Robert"}
	fmt.Println("Person3: ", p3)
}

# Output
{  0}
Person1:  {Rajeev Singh 26}
Person2:  {John Snow 45}
Person3:  {Robert  0}

3. 访问结构体变量及属性

本节介绍如果通过结构体变量和指针访问其属性,以及结构体变量及变量属性的可见性。

3.1 结构体变量访问属性

使用.访问结构体属性:

package main

import (
	"fmt"
)

type Car struct {
	Name, Model, Color string
	WeightInKg         float64
}

func main() {
	c := Car{
		Name:       "Ferrari",
		Model:      "GTC4",
		Color:      "Red",
		WeightInKg: 1920,
	}

	// Accessing struct fields using the dot operator
	fmt.Println("Car Name: ", c.Name)
	fmt.Println("Car Color: ", c.Color)

	// Assigning a new value to a struct field
	c.Color = "Black"
	fmt.Println("Car: ", c)
}
# Output
Car Name:  Ferrari
Car Color:  Red
Car:  {Ferrari GTC4 Black 1920}

3.2 结构体指针访问属性

可以使用&操作符获取结构体变量指针:

package main

import (
	"fmt"
)

type Student struct {
	RollNumber int
	Name       string
}

func main() {
	// instance of student struct type
	s := Student{11, "Jack"}

	// Pointer to the student struct
	ps := &s
	fmt.Println(ps)

	// Accessing struct fields via pointer
	fmt.Println((*ps).Name)
	fmt.Println(ps.Name) // Same as above: No need to explicitly dereference the pointer

	ps.RollNumber = 31
	fmt.Println(ps)
}
# Output
&{11 Jack}
Jack
Jack
&{31 Jack}

上面示例可以看到,通过结构体指针访问其属性无需显示解除引用。

3.3 使用new()方法创建结构体并返回指针

我们可以使用内置new方法创建结构体实例。new方法分配内存空间,并给每个属性设置零值,最后返回内存地址指针:

package main

import "fmt"

type Employee struct {
	Id   int
	Name string
}

func main() {
	// You can also get a pointer to a struct using the built-in new() function
	// It allocates enough memory to fit a value of the given struct type, and returns a pointer to it
	pEmp := new(Employee)

	pEmp.Id = 1000
	pEmp.Name = "Sachin"

	fmt.Println(pEmp)
}
# Output
&{1000 Sachin}

3.4 暴露/隐藏结构体和结构体属性

任何结构体首字母为大写,则外部包可以直接访问。类似的结构体属性的首字母大写则暴露属性。
反之,所有以小写字母开头的仅在包内可见。请看示例:

example
  main
    main.go
  model
    address.go
    customer.go  

** customer.go**

package model

type Customer struct {  // exported struct type
	Id int				// exported field
	Name string			// exported field
	addr address        // unexported field (only accessible inside package `model`)
	married bool  		// unexported field (only accessible inside package `model`)
}

address.go

package model

// Unexported struct (only accessible inside package `model`)
type address struct {
	houseNo, street, city, state, country string
	zipCode                               int
}

main.go入口程序:

package main

import (
	"fmt"
	"example/model"
)

func main() {
	c := model.Customer{
		Id: 1, 
		Name: "Rajeev Singh",
	}

	c.married = true	// Error: can not refer to unexported field or method

	a := model.address{} // Error: can not refer to unexported name

	fmt.Println("Programmer = ", c);
}

我们看到addressmarried 未暴露,不能在main包中访问。

4. 结构体是值类型

结构体是值类型。一个结构体变量赋值给另一个变量,则会产生一个拷贝给另一个变量。类似的,传递结构体给另一个函数,函数获得该结构体的拷贝。当然可以显示传递指针,避免拷贝大对象。

4.1 值类型拷贝

package main

import "fmt"

type Point struct {
	X float64
	Y float64
}

func main() {
	// Structs are value types.
	p1 := Point{10, 20}
	p2 := p1 // A copy of the struct `p1` is assigned to `p2`
	fmt.Println("p1 = ", p1)
	fmt.Println("p2 = ", p2)

	p2.X = 15
	fmt.Println("\nAfter modifying p2:")
	fmt.Println("p1 = ", p1)
	fmt.Println("p2 = ", p2)
}
# Output
p1 =  {10 20}
p2 =  {10 20}

After modifying p2:
p1 =  {10 20}
p2 =  {15 20}

4.2 结构体变量比较

两个结构体如果相应属性相对则变量相等:

package main

import "fmt"

type Point struct {
	X float64
	Y float64
}

func main() {
	// Two structs are equal if all their corresponding fields are equal.
	p1 := Point{3.4, 5.2}
	p2 := Point{3.4, 5.2}

	if p1 == p2 {
		fmt.Println("Point p1 and p2 are equal.")
	} else {
		fmt.Println("Point p1 and p2 are not equal.")
	}
}

因为结构体是值类型,结果变量相等:

# Output
Point p1 and p2 are equal.

总结

本文介绍Golang结构体,通过示例介绍定义、实例化、访问属性。结构体是值对象,实际应用对于大结构体可以使用结构体指针传递参数,避免拷贝大对象影响性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值