如何在 Go 中从函数中访问结构体实例的字段

在 go 中,可通过点号(.)操作符直接访问结构体指针或值的公开字段,前提是字段名首字母大写(即导出字段);若字段为小写,则仅限包内访问。

Go 语言中,结构体字段的可见性由其命名首字母决定:首字母大写的字段(如 Nodes、AdjList)是导出的(public),可被其他包访问;首字母小写的字段(如 nodes、adjList)是未导出的(private),仅能在定义该结构体的包内访问

在你提供的代码中,nodes 和 adjList 均为小写字段,因此它们属于包级私有字段——这本身是良好设计(封装性),但意味着:*即使你持有 `Graph指针(如aGraph),也不能在包外(或同一包的其他函数中)直接读写这些字段,除非该函数位于Graph` 所在的同一包内**。

✅ 正确做法(推荐):将字段改为导出(首字母大写),并配合构造函数和方法保障安全性:

type Graph struct {
    Nodes   []int     // 导出字段,可被外部访问
    AdjList map[int][]int
}

func New() *Graph {
    return &Graph{
        AdjList: make(map[int][]int),
    }
}

// 示例:在另一个顶层函数

中访问字段 func PrintNodeCount(g *Graph) { fmt.Printf("Number of nodes: %d\n", len(g.Nodes)) // ✅ 合法:Nodes 是导出字段 } func main() { aGraph := New() aGraph.Nodes = []int{1, 2, 3} aGraph.AdjList[0] = []int{10, 20} PrintNodeCount(aGraph) // 输出:Number of nodes: 3 }

⚠️ 注意事项:

  • 若坚持使用小写字段(如 nodes),则必须通过方法暴露访问逻辑(如 g.AddNode(n)、g.Nodes()),而非直接访问;
  • 使用 *Graph 指针时,aGraph.nodes 语法完全合法(只要在同包内),但不符合 Go 的封装惯例;
  • new(Graph) 可替换为更惯用的 &Graph{} 或 &Graph{AdjList: make(map[int][]int)};
  • 初始化 map 必须 make,否则直接赋值会 panic(nil map)。

总结:Go 中访问结构体实例字段的核心规则是——字段可见性决定访问范围,点号操作符统一适用。合理设计导出字段 + 提供语义化方法,是兼顾灵活性与安全性的最佳实践。