Golang中如何访问结构体的字段

Golang中如何访问结构体的字段 假设我有一个结构体

type heights struct {
    name   string
    height int // 以英寸为单位
}

假设我有4个实例,其中"Jim"是72英寸,"Mary"是61英寸,"Alex"是69英寸,"Ann"是58英寸。

我如何执行两个查询:

  1. 谁的身高是61英寸?
  2. Ann的身高是多少?

这似乎在我看过的所有教程中都没有解释。

4 回复

@Yamil_Bracho 提出的方法可行,但根据你的需求,可能需要更复杂的处理。

例如,如果列表中的条目数量巨大,遍历整个切片可能会导致性能问题。在这种情况下,你需要使用更复杂的数据结构,比如映射(map)。

所提供的解决方案的另一个问题是,如果存在多个高度相同的条目,它将无法正常工作。

一个稍好一点的方案可能是:

func indexes(persons []Person, fn func(p Person) bool) []int {
    results := make([]int, 0)
    for i, p := range persons {
		if fn(p) {
			results = append(results, i)
		}
	}
	return results
}

更多关于Golang中如何访问结构体的字段的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


更好的做法是将这些“对象”放入一个切片中,然后在该切片中进行搜索。例如

package main

import "fmt"

type Person struct {
	name   string
	height int // 以英寸为单位
}

func index(persons []Person, fn func(p Person) bool) int {
	for i, p := range persons {
		if fn(p) {
			return i
		}
	}
	return -1
}

func main() {
	persons := []Person{
		Person{name: "Jim", height: 72},
		Person{name: "Mary", height: 61},
		Person{name: "Alex", height: 69},
		Person{name: "Ann", height: 58},
	}

	// 谁的身高是61英寸
	pos := index(persons, func(p Person) bool {
		return p.height == 61
	})
	if pos != -1 {
		fmt.Println(persons[pos])
	} else {
		fmt.Println("没有人身高61英寸")
	}

	// Ann的身高是多少
	pos = index(persons, func(p Person) bool {
		return p.name == "Ann"
	})
	if pos != -1 {
		fmt.Println(persons[pos])
	} else {
		fmt.Println("Ann未注册")
	}
}

也许你可以使用一个专门用于集合的包:

GitHub

GitHub - sxyazi/go-collection at golangexample.com

基于泛型类型的、有用的 Go 语言集合函数 - GitHub - sxyazi/go-collection at golangexample.com

GitHub

GitHub - marstr/collection: 几个基本数据结构的通用 Go 语言实现

几个基本数据结构的通用 Go 语言实现。 - GitHub - marstr/collection: 几个基本数据结构的通用 Go 语言实现。

GitHub

GitHub - golang-collections/collections

通过在 GitHub 上创建账户来为 golang-collections/collections 的开发做出贡献。

在Go语言中,访问结构体字段主要有两种方式:直接使用字段名访问,或通过反射机制动态访问。以下是针对你问题的具体实现:

1. 直接字段访问(最常见的方式)

package main

import "fmt"

type Person struct {
    name   string
    height int // 以英寸为单位
}

func main() {
    // 创建实例
    people := []Person{
        {"Jim", 72},
        {"Mary", 61},
        {"Alex", 69},
        {"Ann", 58},
    }
    
    // 查询1: 谁的身高是61英寸?
    fmt.Println("身高61英寸的人:")
    for _, p := range people {
        if p.height == 61 {  // 直接访问height字段
            fmt.Println(p.name)  // 直接访问name字段
        }
    }
    
    // 查询2: Ann的身高是多少?
    fmt.Println("\nAnn的身高:")
    for _, p := range people {
        if p.name == "Ann" {  // 直接访问name字段
            fmt.Printf("%d英寸\n", p.height)  // 直接访问height字段
        }
    }
}

2. 使用map优化查询(适合频繁查询的场景)

package main

import "fmt"

type Person struct {
    name   string
    height int
}

func main() {
    // 创建map以便快速查询
    peopleMap := map[string]Person{
        "Jim":  {"Jim", 72},
        "Mary": {"Mary", 61},
        "Alex": {"Alex", 69},
        "Ann":  {"Ann", 58},
    }
    
    // 查询1: 谁的身高是61英寸?
    fmt.Println("身高61英寸的人:")
    for name, p := range peopleMap {
        if p.height == 61 {
            fmt.Println(name)
        }
    }
    
    // 查询2: Ann的身高是多少?
    fmt.Println("\nAnn的身高:")
    if ann, exists := peopleMap["Ann"]; exists {
        fmt.Printf("%d英寸\n", ann.height)
    }
}

3. 使用反射动态访问字段(当字段名不确定时)

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    name   string
    height int
}

func main() {
    people := []Person{
        {"Jim", 72},
        {"Mary", 61},
        {"Alex", 69},
        {"Ann", 58},
    }
    
    // 查询1: 使用反射查找身高61英寸的人
    fmt.Println("身高61英寸的人:")
    for _, p := range people {
        v := reflect.ValueOf(p)
        height := v.FieldByName("height").Int()
        if height == 61 {
            name := v.FieldByName("name").String()
            fmt.Println(name)
        }
    }
    
    // 查询2: 使用反射获取Ann的身高
    fmt.Println("\nAnn的身高:")
    for _, p := range people {
        v := reflect.ValueOf(p)
        name := v.FieldByName("name").String()
        if name == "Ann" {
            height := v.FieldByName("height").Int()
            fmt.Printf("%d英寸\n", height)
        }
    }
}

4. 封装查询方法(推荐的生产环境做法)

package main

import "fmt"

type Person struct {
    name   string
    height int
}

type People []Person

// 根据身高查找人名
func (p People) FindByHeight(targetHeight int) []string {
    var result []string
    for _, person := range p {
        if person.height == targetHeight {
            result = append(result, person.name)
        }
    }
    return result
}

// 根据人名查找身高
func (p People) FindHeightByName(targetName string) (int, bool) {
    for _, person := range p {
        if person.name == targetName {
            return person.height, true
        }
    }
    return 0, false
}

func main() {
    people := People{
        {"Jim", 72},
        {"Mary", 61},
        {"Alex", 69},
        {"Ann", 58},
    }
    
    // 查询1: 谁的身高是61英寸?
    fmt.Println("身高61英寸的人:")
    if names := people.FindByHeight(61); len(names) > 0 {
        for _, name := range names {
            fmt.Println(name)
        }
    }
    
    // 查询2: Ann的身高是多少?
    fmt.Println("\nAnn的身高:")
    if height, found := people.FindHeightByName("Ann"); found {
        fmt.Printf("%d英寸\n", height)
    }
}

直接字段访问(第一种方法)是最常用和最高效的方式,通过结构体实例.字段名的语法即可访问。对于你的具体问题,第一个查询需要遍历比较height字段,第二个查询需要遍历比较name字段后获取对应的height字段值。

回到顶部