📕
innohub
  • KEEP LEARNING
  • WebInfo
    • JS 部分运算符操作
    • javascript 中的object array
    • 错误处理以及异常捕获
    • JavaScript Bases
    • LaoZi & Confucius
  • PyInfo
    • Python3 输入与输出
    • Python3OS
    • python 修饰器的使用
    • python3 与mysql数据库连接使用实例
    • Format-specifier
    • CGI初学踩坑
    • Django 项目测试
    • Assert-info
    • 使用ngnix和uWSGI配置Django
    • write|SVN​
    • Matplotlib 基本使用
    • 重读 Python 官方文档
    • Python3 Base
    • python3 多线程
    • Python3 函数解析
    • python3 str 对象的基本操作
    • protocl buffers
    • Iterator-Generator
    • Django base
    • Decorator 2
    • Export to wheel or egg-info
    • 三. 运算、数据及逻辑
  • GoInfo
    • Info
      • Select 语句使用
      • First class function
      • Work Pools
      • StructTag
      • Go struct
      • 常用函数
      • Strings操作
      • Golang Bases
      • 数组以及切片
      • 文件操作
      • Golang 中的指针类型
      • Golang Map 类型
      • Reflection
      • 函数闭包
      • 接口
      • Panic and Recover
      • Go中的错误处理
      • 并发
      • defer usage
      • Method in golang
      • Object-oriented Programming
      • Goalng 包管理机制
  • RustInfo
    • Info
      • 包、crate、模块
      • Rust 中的错误处理
      • 智能指针
      • 泛型 generics
      • 数据布局与内存对齐
      • Functions and methods
      • 无畏并发
      • Actix-web 基本使用
      • Got from guessing game
      • 结构体的使用
      • Rust 中的函数式语言功能
      • 集合类型
      • 枚举以及模式匹配
      • Slice 类型
      • 生命周期
      • 测试
      • Rust 中的所有权
      • trait
      • 不安全 Rust
      • Format_print
      • Rust 通用编程概念
      • Macro
  • OS
    • info
      • 内存屏障 -- Part 1
      • 内存屏障 -- Part 2
      • CPU 上下文切换
      • 文件读写与零拷贝
      • ELF 文件
  • MySql
    • info
      • MySql 架构与历史
      • 02-key
  • kubernetes
    • 第二章 k8s 基本概念
    • 第一章 Kubernetes -- 伟大舵手
  • Redis
    • info
      • Redis 总览
      • 02-underline-ds
  • Shell&CInfo
    • GCC 与make的使用
    • C++ 中 malloc 与 new
    • 位运算符操作
    • Base of C macro
    • C 语言中 extern 关键字的用法
  • Distributed
    • info
      • 分布式理论概述
  • Java
    • info
      • Java 内存模型
  • Prometheus
    • Prometheus -- 不灭之火
Powered by GitBook
On this page
  • 1. 结构体的组成
  • 1.1 声明一个结构体
  • 2. 结构体的访问
  • 1.3 结构体的比较
  • 2. 匿名与可导出
  • 2.1 匿名域
  • 2.2 嵌套结构体
  • 2.3 结构体提升域
  • 2.4 可导出的结构体以及可见域

Was this helpful?

  1. GoInfo
  2. Info

Go struct

[TOC]

1. 结构体的组成

在golang中结构体与c中的相似,是一些域的集合,适用于将多个数据域作为同一个抽象概念的场景。结构体的定义以及声明需要使用大括号。使用关键字type 定义一个结构体,结构体中的一个每一个属性需要明确定义其名称,多个相同类型的属性可以写在一行并且使用逗号隔开。

也可以不使用关键字type 定义结构体,可以使用var定义一个匿名结构体。没有新定义一个类型。

1.1 声明一个结构体

type People struct {
    firstName string
    lastName string
    age int
}

var People = struct {
    firstName, lastName string
    age int   //不需要逗号,因为类型后面不会自动补;
}{
    "Jack",
    "Ma",
    60,      //需要逗号,否则会自动填充分号
}

声明一个匿名结构体时,需要定义结构体的属性不需要指明结构体的名称,即没有给该结构体声明一个特定的类型。获取其类型时会输出struct {} 的定义格式。

var people = struct {
  firstName, lastName string
  age int
}{
  "Jack",
  "Ma",
  60,
}


emp1 := Employee {
    firstName: "Sam",
    secondName: "Bryant",
    age: 23,
    salary: 5000,
  }

  emp2 := Employee{"Tomoas", "Paul", 29, 20000}
  fmt.Printf("Employee 1, %v, %s, %T\n", emp1, reflect.TypeOf(emp1), emp1)
  fmt.Println("Employee 2,", emp2, reflect.ValueOf(emp2).Kind())

  fmt.Println("People:", people, reflect.TypeOf(people))
  fmt.Println("Normal struct and anonymous struct type diff:")
  fmt.Printf("Anonymous struct: %T\n", people)
  fmt.Printf("Struct: %T\n", emp1)
// Output:
// Employee 1, {Sam Bryant 23 5000}, main.Employee, main.Employee
// Employee 2, {Tomoas Paul 29 20000} struct
// People: {Jack Ma 60} struct { firstName string; lastName string; age int }
// Normal struct and anonymous struct type diff:
// Anonymous struct: struct { firstName string; lastName string; age int }
// Struct: main.Employee

2. 结构体的访问

golang中结构体的访问与c的一致,相当于public 的类,可以直接对于一个结构体变量中的任何一个属性进行访问赋值。同时可以声明一个没有初始值的结构体其所有的属性值将会按照属性类型的默认值进行赋值。

如下代码,对于string类型赋予默认值"" ,对于int类型赋予0

  fmt.Println("\n\nTest for accessing to elements of struct:")
  emp1 := Employee{firstName: "John", secondName: "James"}
  var emp2 Employee
  fmt.Println("Employee 3:", emp1, "Employee 4:", emp2)

  fmt.Println("Now assign to emp3 and emp4")
  emp2.firstName = "Mike"
  emp2.secondName = "Don"
  emp2.age = 23
  emp2.salary = 2000
  emp1.firstName = "Test"
  emp1.age = 30
  emp1.salary = 30000
  fmt.Println("Employee 3:", emp1, "Employee 4:", emp2)

// Test for accessing to elements of struct:
// Employee 3: {John James 0 0} Employee 4: {  0 0}
// Now assign to emp3 and emp4
// Employee 3: {Test James 30 30000} Employee 4: {Mike Don 23 2000}

1.3 结构体的比较

结构体可以使用==进行判断两个相同类型的结构体的值是否相等。但是需要注意,定义的结构体的每一个属性必须是可以比较的。

func equal() {
  emp1 := Employee{"Mike", "Tang", 66, 9000}
  emp2 := Employee{"Mike", "Tang", 66, 90}

  if emp1 == emp2 {
    fmt.Println("The same employee")
  } else {
    fmt.Println("Not one")
  }

  type image struct {
    data map[int]int
  }

  image1 := image{data: map[int]int{
    0: 188,
  }}
  image2 := image{data: map[int]int{
    0:188,
  }}

  if image1 == image2 {
    fmt.Println("Same image")
  } else {
    fmt.Println("not one")
  }
}

// ./struct_.go:132:13: invalid operation: image1 == image2 (struct containing map[int]int cannot be compared)

2. 匿名与可导出

2.1 匿名域

对于结构体可以进行匿名声明,不需要指明其具体类型。对于结构体中的域也可以指明其名称只需要指明其类型,即为匿名域,匿名属性。匿名属性的访问可以使用variable.type 的格式。指明结构体变量的某一个类型的属性,即可以进行访问。但是注意此时匿名域的类型必须不同,否则会报错ambigous selector

  fmt.Println("\n\n")
  type People struct {
    string
    int
  }
  p1 := People{"Michale", 50}
  fmt.Println(p1, p1.string, p1.int)

2.2 嵌套结构体

结构体可以进行嵌套,因为对于一个结构体而言,其每一个域都可以是任意类型。一个结构体可以作为另一个结构体的属性进行嵌套。对于结构体内部的结构体的属性,需要使用两次.才可以进行访问。

package main

import (  
    "fmt"
)

type Address struct {  
    city, state string
}
type Person struct {  
    name string
    age int
    address Address
}

func main() {  
    var p Person
    p.name = "Naveen"
    p.age = 50
    p.address = Address {
        city: "Chicago",
        state: "Illinois",
    }
    fmt.Println("Name:", p.name)
    fmt.Println("Age:",p.age)
    fmt.Println("City:",p.address.city)
    fmt.Println("State:",p.address.state)
}

2.3 结构体提升域

对于嵌套结构体而言,为了直接访问嵌套在内部的结构体,可以使用匿名域作为内部结构体的域。此时内部结构体的所有属性的能访问都进行了提升,可以使用外部变量进行直接访问。而不需要使用两次点操作符。

type People struct {
  name string
  age int
  Address    // Promoted field, can be access by variable directly
}

type Address struct {
  city, street string
}

var p People
p.name = "Jackon"
p.age = 30
p.Address = Address {
    city: "Beijing",
    street: "二环",
}
fmt.Println(p, p.Address.city, p.street)

2.4 可导出的结构体以及可见域

与golang中的包管理机制一致,为了可以在其他包访问定义的结构体,可以使用大写字母作为定义类型的首字母。对于结构体中的属性,其可见性也按照这种机制,包外访问的只能是可导出结构体的首字母大写的属性.

import "github.com/nf/computer"

func exported() {
  var spec computer.Spec
  spec.Maker = "Apple"
  spec.model = "fdsfsd"   // 包外不可见属性
  spec.Price = 5000.80
  fmt.Println(spec)
}
// # command-line-arguments
// ./struct_.go:106:7: spec.model undefined (cannot refer to unexported field or method model)
PreviousStructTagNext常用函数

Last updated 5 years ago

Was this helpful?