Go语言中的结构体

6

我刚开始学习Go语言,正在查看它们的教程(https://golang.org/doc/code.html)。

在其中的一个例子中,他们将一个变量设置为结构体,但是我很困惑他们如何在下面的for循环中访问结构体的成员?有没有人可以澄清一下?非常感谢!

代码:

package stringutil

import "testing"

func TestReverse(t *testing.T) {
    cases := []struct {
        in, want string
    }{
        {"Hello, world", "dlrow ,olleH"},
        {"Hello, 世界", "界世 ,olleH"},
        {"", ""},
    }
    for _, c := range cases {
        got := Reverse(c.in)
        if got != c.want {
            t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
        }
    }
}

他们没有将变量设置为结构体,而是将其设置为结构体切片。 - Amit Kumar Gupta
2个回答

8
以下是带有一些注释的代码,以帮助澄清每个语句在其中的作用。
import "testing"

func TestReverse(t *testing.T) {
    cases := []struct { // declaration of anonymous type
        in, want string // fields on that type called in and want, both strings
    }{
        {"Hello, world", "dlrow ,olleH"},
        {"Hello, 世界", "界世 ,olleH"},
        {"", ""},
    } // composite literal initilization
    // note the use of := in assigning to cases, that op combines declaration and assignment into one statement
    for _, c := range cases { // range over cases, ignoring the index - the underscore means to discard that return value
        got := Reverse(c.in) // c is the current instance, access in with the familiar dot notation
        if got != c.want { // again, access operator on c, the current instance
            t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want) // more access
        }
    }
}

如果这有帮助的话,请告诉我。 如果您对某些语句仍然感到困惑,我可以尝试用口语给出更多摘要或添加更多细节。此外,如果您不熟悉“范围”是指对集合进行迭代,返回k,v,其中k是索引或键,而v是值。

编辑:关于cases的声明/初始化的详细信息

    cases := []struct {
        in, want string
    }

这对花括号内的内容是一个结构体的定义。这是一个匿名类型,正常的声明应该像这样:

    type case struct {
        in string
        want string
    }

如果你有这样的东西,那么在该包的范围内会有一个名为case的类型(未导出,如果您想使其“公共”,则需要将其更改为type Case)。相反,示例结构体是匿名的。它的工作方式与普通类型相同,但作为开发人员,您将无法引用该类型,因此只能实际使用此处初始化的集合。在内部,此类型与具有2个未导出字符串字段的任何其他结构体相同。字段名为inwant。请注意,在此赋值中cases:= []struct之前有[],这意味着您正在声明此匿名类型的切片。
接下来的小部分称为静态初始化。这是一种初始化类型集合的语法。像{"",""}这样的每个嵌套位都是其中一个匿名结构的声明和初始化,再次用花括号表示。在这种情况下,您将两个空字符串分别分配给inwant(如果不使用名称,则顺序与定义中的顺序相同)。外层的大括号是为了切片。如果您的切片是int或string之类的,则可以直接使用值而不需要额外的嵌套级别,例如myInts:= []int {5,6,7}
    {
        {"Hello, world", "dlrow ,olleH"},
        {"Hello, 世界", "界世 ,olleH"},
        {"", ""},
    }

代码如何通过c.in和c.out访问结构中的字符串? - thegreenfrog
1
@thegreenfrog 循环正在迭代结构体的切片,共有3个。每一行 {"Hello, world", "dlrow ,olleH"} 都是实例化一个结构体。for _, c := range cases 更多地是一个 foreach 循环,我会将其解读为“对于 cases 中的每个 c”,. 通常被称为访问运算符(不确定 Go 是否有与此不同的特定名称),您可以使用它来访问结构体上的属性。如果我有一些结构体 A,其中包含一些字段 OneTwoThree,我可以从类型为 A 的实例 a 中访问这些字段,例如 a.Onea.Twoa.Three - evanmcdonnal
如果您需要进一步的澄清,我可以在答案中详细说明。如果您对访问运算符的使用不熟悉,我建议您进行一些关于面向对象编程的通用阅读,因为它几乎在每种语言中都被使用。 - evanmcdonnal
好的,所以inwant本质上是我们用来访问每个切片中的两个元素的变量? - thegreenfrog
@thegreenfrog 我会在答案中更新这个。在这个例子中,声明结合了几个不同的概念,如果我把代码分开,会更清楚明白。 - evanmcdonnal
哇,谢谢你的跟进。那真是一个非常详尽和深入的解释! - thegreenfrog

1

介绍一下 struct 是什么。

在 struct 中声明变量,然后可以从函数中使用它们。

例如:

package main

import (
    "fmt"

)

func main() {
    Get()

}

func Get(){
    out := new(Var)

    out.name = "james"

    fmt.Println(out.name)
}
type Var struct {
    name string
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接