Skip to main content
 首页 » 编程设计

Golang Struct 示例教程

2022年07月19日118zhenyulu

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


本文参考链接:https://blog.csdn.net/neweastsun/article/details/107286465
阅读延展