The various flags I set up at the beginning of the year have been thrown out of my mind. Half of 2018 has passed, and I finally started my third article. There are only 27 articles left in my annual output plan of 30 articles, and I am “confident to complete” the rest.

At the beginning of 2018, I began to transfer from PHP to Go development direction. Although the learning route was not very steep, I encountered many pits and interesting places in the process, and I couldn’t help but summarize and share with you. Today I’m going to talk about a few ways to initialize variables in Go.

A move in Go to initialize a value type

Golang’s data types can be divided into value types and reference types. Let me summarize the initialization of value types (string as an example) in Go:

var a1 string
fmt.Printf("a1: %#v \n", a1) // a1: ""

var a2 *string
fmt.Printf("a2: %#v \n", a2) // a2: (*string)(nil)
// panic: runtime error: invalid memory address or nil pointer dereference
//fmt.Printf(**"a2: %#v \n"**, *a2)

a3 := new(string)
fmt.Printf("a3: %#v \n", a3) // a3: (*string)(0xc42000e200)
fmt.Printf(**"a3: %#v \n"**, *a3) // a3: ""

a4 := "hello"
fmt.Printf("a4: %#v \n", a4) // a4: "hello"

a5 := string("hello")
fmt.Printf("a5: %#v \n", a5) // a5: "hello"

a6 := &a5
fmt.Printf("a6: %#v \n", a6) // a6: (*string)(0xc42000e1e0)

// Error: cannot make type string
//a7 := make(string, 1)

// Cannot take the address of string("hello")
//a8 := &string("hello")

Copy the code

The comment section is the output information, you can see that some results are typed as a value, some as a pointer. In this part, I just want to make two points:

  1. Go automatically initializes the declaration variable to a value of 0: int is 0, string is null, bool is false, and so on
  2. For a variable created by new, is a pointer, which is different from the variable declared by var, which is just nil. New (string) allocates a chunk of memory for string, initialized to 0. You can understand the error message in the comments above.

A move in Go to initialize a reference type

This is the point I want to make. There are only three reference types in Go ::map:: ::slice:: ::channel:: for example, slice is used.

var s1 []string
fmt.Printf("s1: %#v\n", s1) // s1: []string(nil)
s1 = append(s1, "hello")
fmt.Printf("s1: %#v\n", s1) // s1: []string{"hello"}

var s2 *[]string
fmt.Printf("s2: %#v\n", s2) // s2: (*[]string)(nil)

s3 := []string{"a"."b"."c"}
fmt.Printf("s3: %#v\n", s3) // s3: []string{"a", "b", "c"}

s4 := &[]string{}
fmt.Printf("s4: %#v\n", s4) // s4: &[]string{}

s5 := &s3
fmt.Printf("s5: %#v\n", s5) // s5: &[]string{"a", "b", "c"}

s6 := new([]string)
fmt.Printf("s6: %#v\n", s6) // s6: &[]string(nil)
// first argument to append must be slice; have *[]string
//s6 = append(s6, "hello") // This is a null reference pointer, so an error is reported

s7 := make([]string.0)
fmt.Printf("s7: %#v\n", s7) // s7: []string{}

// If you have a problem, you can use this method
s8 := new([]string)
*s8 = make([]string.0)
fmt.Printf("s8: %#v\n", s8) // s8: &[]string{}

arr := [5]string{"a"."b"."c"}
s9 := arr[:]
fmt.Printf("s9: %#v\n", s9) // s9: []string{"a", "b", "c", "", ""}

Copy the code

Here I will focus on the analysis of s6, S7, S8 these three initialization modes. So s6, I’m going to use new.

New (T) allocates a chunk of memory for each new type T, initialized to 0, and returns a memory address of type *T: this method returns a pointer to an address of type T with a value of 0, which is not the value 0, but the default value 0 for go, corresponding to ::slice:: nil.

This is definitely not the way to initialize ::slice:: in Go. Why? I’ll briefly mention it here because ::slice:: in Go is defined as follows:

type slice struct{
	array unsafe.Pointer
	len   int
	cap   int
}

Copy the code

:: Slice :: :: :: :: :: :: :: :: :: :: : new :: T :: T: T: T: T: T: T If so, do you think there is something wrong with it?

Initialization of slice requires initialization of len, cap and array to point to an array pointer. Once these initializations are complete, Slice can be used normally.

conclusion

Initialization of a custom structure is the same as initialization of string, map, channel, and slice. You can write some code yourself

  • Remember that make only works for map, slice, and channel and does not return Pointers.
  • To get an explicit pointer, assign it using new, or explicitly use the address of a variable.

What you plan to share next:

  1. Go value, reference, pointer knowledge, focus on the function parameter passing way
  2. In Go ::slice:: intimate relationship with ::array::
  3. Go interface knowledge, from ::sort:: source code perspective