Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Structs in GoLang

Tags:

struct

go

I am just starting with GoLang, and I am looking at one of their tutorials (https://golang.org/doc/code.html).

In one of their examples, they set a variable to a struct, but I am so confused as to how they are accessing elements of the struct in the for loop below? Any chance someone can clarify? Thanks alot!

Code:

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)
        }
    }
}
like image 659
thegreenfrog Avatar asked Dec 18 '15 19:12

thegreenfrog


People also ask

What are structs in Golang?

A structure or struct in Golang is a user-defined type that allows to group/combine items of possibly different types into a single type. Any real-world entity which has some set of properties/fields can be represented as a struct.

How do you write a struct in Golang?

Defining a struct typeThe type keyword introduces a new type. It is followed by the name of the type ( Person ) and the keyword struct to indicate that we're defining a struct . The struct contains a list of fields inside the curly braces. Each field has a name and a type.

What is the difference between struct and interface in Golang?

Structs and interfaces are Go's way of organizing methods and data handling. Where structs define the fields of an object, like a Person's first and last name. The interfaces define the methods; e.g. formatting and returning a Person's full name.

Can Golang structs have methods?

Structs consist of data, but apart from this, structs also tell about the behavior in the form of methods. Methods attached to structs is very much similar to the definition of normal functions, the only variation is that you need to additionally specify its type.


2 Answers

Below is the code with some comments to help clarify each statements role in this.

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
        }
    }
}

Let me know if that helps. I can try giving more of a summary in spoken language or add more details if some of the statements don't make sense still. Also, fyi if you're not familiar range 'ranges' over a collection, returning k, v where k is the index or key and v the value.

EDIT: details on the declaration/initilization of cases

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

This bit inside the first pair of curly braces is the definition of a struct. This is an anonymous type, a normal declaration would look like this;

    type case struct {
        in string
        want string
    }

If you had something like this then there would be a type called case in the scope of this package (not exported, if you wanted to make it 'public' so it would need to be type Case instead). Instead the examples struct is anonymous. It works the same as normal type, however as a developer, you will have no way to reference that type so you can only practically work with the collection initialized here. Internally this type is the same as any other struct with 2 unexported strings for fields. The fields are named in and want. Notice that in the assignment here cases := []struct you have [] before struct this means you're declaring a slice of this anonymous type.

This next little bit, is called static initialization. This is a syntax for initializing collections as types. Each of these nested bits like {"", ""} is the declaration and initilization of one of these anonymous structs, denoted again by the curly braces. In this case you're assigning two empty strings to in and want respectively (if you don't use names, the order is the same as in the definition). The outer pair of braces is for the slice. If your slice were of say int's or string's, then you would just have the values right there without the extra level of nesting like myInts := []int{5,6,7}.

    {
        {"Hello, world", "dlrow ,olleH"},
        {"Hello, 世界", "界世 ,olleH"},
        {"", ""},
    }
like image 110
evanmcdonnal Avatar answered Sep 28 '22 07:09

evanmcdonnal


Go root of what is a struct.

you declare your variables in it so then you can use it from a function. Example:

package main

import (
    "fmt"

)

func main() {
    Get()

}

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

    out.name = "james"

    fmt.Println(out.name)
}
type Var struct {
    name string
}
like image 35
harold ramos Avatar answered Sep 28 '22 09:09

harold ramos