This is a creation in Article, where the information may have evolved or changed.
Go has pointers. However, there are no pointer operations, so they are more like references than the pointers you know from C. Pointers are very useful. When calling a function in Go, remember that the variable is the value passed. Therefore, in order to modify the efficiency and probability of a value passed into the function, a pointer is available.
var p *intfmt.Printf("%v", p) // 打印nilvar i int // 定义一个整型变量ip = &i // 使得p指向ifmt.Printf("%v", p) // 打印出来的内容类似0x7ff96b81c000a
Memory allocation
Allocating memory with new
The built-in function new is essentially the same as the function function of the same name in other languages: new (t) allocates a 0 value to fill the memory space of type T, and returns its address, a value of type *t. In the terms of Go, it returns a pointer to the 0 value of the newly assigned type T. It is important to remember this.
allocating memory with Make
The built-in function make (T, args) has different functions from new (t). It can only create slice,map and channel, and returns a T type with an initial value (not 0) instead of *t. Essentially, the reason that these three types are different is that references to data structures must be initialized before they are used. For example, a slice is a three-item descriptor that contains pointers to data (internal array), length and capacity, and slice is nil until those items are initialized. For Slice,map and Channel,make, the internal data structure is initialized, and the appropriate values are populated.
New assignment; make initialization
- New (T) returns *t pointing to a 0 value T
- Make (t) returns the initialized T
Make is only available for Map,slice and channel, and is not a pointer returned. A specific pointer should be obtained with new.
Constructors and declaration of conformity
func NewFile(fd int, name string) *File { if fd<0 { return nil } f := File{fd, name, nil, 0} // 创建一个新的File return &f // 返回 f 的地址 }
There is no problem returning the address of the local variable, and the associated storage area is still present after the function returns. In fact, getting the address of an allocated instance from a composite declaration is better (getting an address from a composite declaration means telling the compiler to allocate space in the heap instead of the stack), so you can eventually shorten the two rows to one line.
return &File{fd, name, nil, 0}
All items (called fields) must be written in order. However, the initialization content can appear in any order by using the field: value-paired identification of the element, and the field initialized to a value of 0 can be omitted. So it can be
return &File{fd: fd, name: name}
In a particular case, if the composite declaration does not contain any fields, it creates a 0 value of a specific type. The expression new(File) and &File{} is equivalent.
Compound declarations can also be used to create array,slice and maps, identifying fields by specifying the appropriate index and map keys. In this case, either Enone,eio or Einval initialization works well, just make sure they're different.
ar := [...] s t r i n g { Enone: "no error", Einval: "invalid argument" } sl := [] s t r i n g { Enone: "no error", Einval: "invalid argument" }ma := map[int]string {Enone: "no error", Einval: "invalid argument"}
Define your own type
Go allows you to define a new type, implemented by the keyword type:
For example:
type foo int \\ 创建了一个新的类型 foo 作用跟 int 一样\\ 创建更加复杂的类型需要用到 struct 关键 字。package mainimport "fmt"type NameAge struct { name string // 首字母小写,不导出 age int // 不导出}func main() { a := new(NameAge) a.name = "Pete"; a.age = 42 fmt.Printf("%v\n", a) // 输出&{Pete 42}}
Method
There are two ways to create a function for a newly defined type:
// 1、创建一个函数接受这个类型的参数。func doSomething(n1 *NameAge, n2 int) { /* */ }// 2、创建一个接收方是该类型的方法func (n1 *NameAge) doSomething(n2 int) { /* */ }//方法调用方式var n *NameAgen.doSomething(2)
// Mutex 数据类型有两个方法,Lock 和 Unlock。type Mutex struct { /* Mutex 字段 */ } func (m *Mutex) Lock(){ /* Lock 实现 */ } func (m *Mutex) Unlock(){ /* Unlock 实现 */ }//现在用两种不同的风格创建了两个数据类型。type NewMutex Mutextype PrintableMutex struct {Mutex}//现在 NewMutux 等同于 Mutex,但是它没有任何 Mutex 的方法。换句话说,它的方法 是空的。但是 PrintableMutex 已经从 Mutex 继承了方法集合。*PrintableMutex 的方法集合包含了 Lock 和 Unlock 方法,被绑定到其匿名字段 Mutex。
Transformation
Go supports converting one type to another
// 1、string->byte或rune的slicemystring := "hello this is string"byteslice := []byte(mystring) // 转换成byte slice,每个byte保存字符串对应字节的整数值。注意Go的字符串是UTF-8编码,字节长度不定。runeslice := []rune(mystring) // 转换到rune slice,每个rune保存Unicode编码的指针。字符串中的每个字符对应一个整数。// 2、从字节或整型的slice到stringb := []byte {'h','e','l','l','o'} // 复合声明 s := string(b)i := []rune {257,1024,65}r := string(i)// 3、数值的转换• 将整数转换到指定的(bit)长度:uint8(int);• 从浮点数到整数:int(float32)。这会截断浮点数的小数部分; • 其他的类似:float32(int)。// 4、用户定义类型的转换type foo struct { int } // 匿名字段 type bar foo // bar是foo的别名var b bar = bar{1} // 声明b为bar类型var f foo = b //,不能使用b(类型bar)作为类型foo赋值var f foo = foo(b)//,可以通过此方式转化
Combination
Go is not an object-oriented language and therefore does not inherit. However, there are times when you need to "inherit" from an already implemented type and modify some methods. It can be implemented in Go in a way that embeds a type.