First, the basic situation

1.1. Basic introduction to Golang

The Go language, or Golang, began in 2007 and was officially released in 2009. Go is a very young language whose main goal is to “combine the speed of dynamic languages like Python with the performance and security of compiled languages like C/C++.”

The launch of Go language aims to reduce the complexity of the code without losing the performance of the application. IT has the advantages of “simple deployment, good concurrency, good language design, good execution performance” and so on. At present, many IT companies in China have adopted Go language for their development projects.

Go is sometimes described as a “C-like language,” or “C for the 21st century.” Go inherits similar expression syntax, control flow structure, basic data types, call parameter values, Pointers, and many other ideas from C, as well as the efficiency of compiled machine code and the seamless adaptation of existing operating systems that C has always looked at.

Because the Go language has no concept of classes or inheritance, it doesn’t look the same as Java or C++. But it implements polymorphism through the concept of interfaces. The Go language has a lightweight type system that is clear and easy to understand, and there is no hierarchy between types. So Go is a hybrid language.

In addition, many important open source projects have been developed using the Go language, including Docker, Go-Ethereum, Thrraform, and Kubernetes.

According to the latest Tiobe programming Language rankings for September 2020, Golang is currently ranked 11th in usage:

1.2 Golang Usage Scenarios

  1. Server-side development (with gin, GORM and other libraries to achieve high performance back-end services)
  2. Container development (for example, Docker, K8s are based on Golang)
  3. Scripting development (Golang can also be used as an alternative to Python because it is easy to deploy itself and interact with the operating system apis)
  4. Development of underlying tools (alternative to C or C++ for developing operating system underlying tools)

Second, basic grammar

2.1 coding protocol

Golang is a strict engineering language, mainly reflected in the coding style and visibility rules. In Java, multiple coding styles are allowed to coexist. For example, the following two method declarations are allowed for Java:

public String getString(Integer num) {
    return num.toString();
}

public String getString(Integer num) 
{
    return num.toString();
}
Copy the code

1. Open and close curly braces should be in a newline style

In Golang, only one style of newline is allowed:

func getString(num int) string {
	return strconv.Itoa(num)
}
Copy the code

If the following newline style occurs, an error will be reported and the compilation will not be completed:

2. The variable must be used after declaration. If not, use _ instead

In Java, a variable can be declared but not used. Golang’s variable must be used. Otherwise, you need to replace the variable name with _, indicating that the variable will not be used more than:

func getString(num int) string {
	temp := num // Cannot compile without users
	_ := num	// Compile normally
	return strconv.Itoa(num)
}
Copy the code

3. Visibility domain rules

Whereas Java controls the visibility of methods, variables, and classes by using the private, protected, and public keywords, Golang controls the visibility only in one way: when the field starts with an uppercase letter, it is visible to the outside world; when it starts with a lowercase letter, it is visible to the inside members of the package.

  • entity
package entity

type Person struct {
	Name string
	Age int
	id string
}

type student struct {
	detail Person
}

func test(a) {
	// This package is visible
	person := &student{detail: Person{
		Name: "ARong",
		Age:  21,
		id:   "211",
	}}
	fmt.Println(person)
}
Copy the code
  • main
package main

import (
	"fmt"
	entity "others/scope"
)

func main(a) {
	// The id field is not visible
	person := &entity.Person{
		Name: "ARong",
		Age:  21,
	}
	fmt.Println(person)
}
Copy the code

2.2. Variable declaration and initialization

In Java, the common syntax for variable declaration and initialization is:

    // Object: type to declare, v: variable name, new Object() variable initialization
    Object v = new Object();
Copy the code

Golang uses the var keyword to declare variables:

    // var: variable definition, v1: variable name, int: variable type
    var v1 int
	var v2 string
	var v3 [10]int  / / array
	var v4 []int // Array slice
	var v5 struct {
		f int
	}
	var v6 *int / / pointer
	var v7 map[string]int  // Map. Key is a string and value is an int
	var v8 func(a int) int
	var v9,v10 int // Both v9 and v10 are declared as int
Copy the code

You can also use := automatically infer the variable type:

	var v1 int = 10 // The correct way to use 1
	var v2 = 10  // The compiler can automatically deduce the type of v2 by using the correct method 2
	v3 := 10  // The compiler can automatically deduce the type of v3 when using the correct mode 3
Copy the code

2. For basic types, declaration is initialization. For reference types, the declaration is initialized to nil

In Java, if you declare a variable inside a method but do not initialize it, you will get a compilation error when using it:

public void solve(a) {
    int num;
    Object object;
    System.out.println(num); // Compile error
    System.out.println(object); // Compile error
}
Copy the code

In Golang, for basic types, declaration is initialization; For reference types, the declaration is initialized to nil. This can greatly avoid the occurrence of NPE.

func main(a) {
	var num int
	var hashMap *map[string]int
	fmt.Println(num) // num = 0
	fmt.Println(hashMap) // &hashMap== nil
}
Copy the code

2.3. Value type and reference type

Golang’s type system is similar to That of Java, but it’s important to note that arrays in Java are reference types, whereas arrays in Golang are value types. When passing an array to a method, Java can directly modify the inner values of the array (a shallow copy). Golang, however, makes a full copy (a deep copy) :

  • Java
    public static void main(String[] args) {
        int[] array = {1.2.3};
        change(array);
        System.out.println(Arrays.toString(array)); / / - 1, 2, 3
    }

    private static void change(int[] array) {
        array[0] = -1;
    }
Copy the code
  • Golang
func main(a) {
	array := [...]int{1.2.3}
	change(array)
	fmt.Println(array) / / 1, 2, 3
}

func change(array [3]int) {
	array[0] = - 1
}
Copy the code

It is also worth noting that in Golang, only arrays of the same length and type are considered to be of the same type. For example, [2]int and [3]int are considered to be of different types. This causes a compilation error when passing arguments.

So arrays are rarely used directly in Golang, and slices (based on array Pointers) are used instead of arrays.

In Golang, only slice, pointer, channel, map, and func are reference types, which means that when you pass arguments, you are essentially copying their Pointers. Internal changes directly affect external ones:

func main(a) {
	slice := []int{1.2.3}
	changeSlice(slice)
	fmt.Println(slice) / / - 1, 2, 3

	mapper := map[string]int {
		"num": 0,
	}
	changeMap(mapper)
	fmt.Println(mapper) // num = -1

	array := [...]int{1.2.3}
	changePointer(&array)
	fmt.Println(array) / / - 1, 2, 3

	intChan := make(chan int.1)
	intChan <- 1
	changeChannel(intChan)
	fmt.Println(<- intChan) // -1
}

func changeChannel(intChan chan int) {
	<- intChan
	intChan <- - 1
}

func changePointer(array *[3]int) {
	array[0] = - 1
}

func changeMap(mapper map[string]int) {
	mapper["num"] = - 1
}

func changeSlice(array []int) {
	array[0] = - 1
}
Copy the code

Structs, functions and Pointers

3.1 declaration and use of structure

The most striking difference between Golang and Java is that there is no such thing as a “class” in Golang. The structures that organize data entities are called structures in Golang. Functions can exist outside of a “class,” and can be called depending on a structure or a package name.

Structures in Golang abandon the concept of polymorphism such as inheritance and implementation, and use combinations between structures to achieve the effect of reuse methods or fields.

To declare a structure, use the type + struct keyword:

type Person struct {
	Name string
	Age  int
	id   string
}
Copy the code

To use a structure is also simple. There are several ways to create a structure:

    personPoint := new(entity.Person) // Create a pointer to the structure using the new method
	person1 := entity.Person{} // Create the default field structure with Person{}
	person2 := entity.Person{ Person{Name:x,Age:x} creates the structure and initializes the specific fields
		Name: "ARong",
		Age:  21,
	}
	fmt.Println(personPoint) // &{ 0 }
	fmt.Println(person1)     / / {0}
	fmt.Println(person2)	 // {ARong 21 }
Copy the code

3.2. Differences between functions and methods

Those of you who use Java should use the word “function” very rarely, because for Java, all “functions” are built around the concept of “classes,” meaning that only “classes” contain so-called “functions,” which are called “methods.”

And the word “function” comes from process-oriented languages, so the basic difference between “function” and “method” in Golang is:

Functions are not called based on a structure but on a package name, and methods are called based on a structure.

Here’s an example to see the difference between a method and a function:

  • entity
package entity

import "fmt"

type Person struct {
	Name string
	Age  int
	id   string
}

// Person structure/pointer to callable "methods" that belong to the Person structure
func (p *Person) Solve(a) {
	fmt.Println(p)
}

// A "function" that can be called anywhere and does not belong to any structure can be called by entity.solve
func Solve(p *Person) {
	fmt.Println(p)
}
Copy the code
  • main
func main(a) {
	personPoint := new(entity.Person) // Create a pointer to the structure using the new method

	entity.Solve(personPoint) // Call the function
	
	personPoint.Solve() 	  // Method call
}
Copy the code

3.3. Use of Pointers

There is no explicit pointer operation in Java, and there is explicit pointer operation in Golang, but Golang’s pointer is not as complex as C’s to perform pointer operation.

Here’s an example of Java’s implicit pointer conversion and Golang’s explicit pointer conversion: Both the Java and Golang methods pass value types. In Java, if you pass a reference type (object, array, etc.), the pointer to it will be copied. In Golang, you must explicitly pass the Person pointer, or you will just pass a copy of the object.

Golang uses * to define and declare Pointers, and & to get Pointers to objects.

func main(a) {
	p1 := entity.Person{
		Name: "ARong1",
		Age:  21,
	}
	changePerson(p1)
	fmt.Println(p1.Name) // ARong1
	changePersonByPointer(&p1)
	fmt.Println(p1.Name) // ARong2
}

func changePersonByPointer(person *entity.Person) {
	person.Name = "ARong2"
}

func changePerson(person entity.Person) {
	person.Name = "ARong2"
}
Copy the code

Note that if other structures need to be combined within a structure, it is recommended to declare them as Pointers, otherwise updates will be lost.

Here is an implicit pointer conversion to the Golang method, which is automatically converted to a pointer call if an object is passed from a structure:


type Person struct {
	Name string
	Age  int
}

// Person structure/pointer to callable "methods" that belong to the Person structure
func (p *Person) Solve(a) {
	fmt.Println(p)
}


func main(a) {
	p := entity.Person{
		Name: "ARong",
		Age:  21,
	}
	
	pp := &p
	pp.Solve() / / explicit
	
	p.Solve    // Implicit, automatically convert p to &p
}
Copy the code