Go language Introduction (top)-syntax

Source: Internet
Author: User
Tags control characters email string key string sprintf
This is a creation in Article, where the information may have evolved or changed.

Weekend weather is not good, can only stay at home, so on the way to see the go language, feel more interesting, so write an article introduction. I want to write an article that you can get an initial understanding of a language when you commute by subway or bus . Therefore, the following article is mainly based on code and comments. Just need you to C language, Unix,python have a little foundation, I believe you will read in about 30 minutes and have some preliminary understanding of the go language.

Hello World

File name Hello.go

package main //声明本文件的package名import "fmt" //import语言的fmt库——用于输出func main() {    fmt.Println("hello world")}

Run

You can have two modes of operation,

Explanation Execution (actually compiled into a.out and then executed)

$go run hello.gohello world

Compile execution

$go build hello.go$lshello hello.go$./hellohello world

Your own package

You can use the GOPATH environment variable or use a relative path to import your own package.

The conventions of Go are this:

    • In import, you can use a relative path, such as./or: /To quote your package
    • If you do not use a relative path, go will look for the $gopath/src/directory.

Using relative paths

import "./haoel"  //import当前目录里haoel子目录里的所有的go文件

Using the Gopath path

import "haoel"  //import 环境变量 $GOPATH/src/haoel子目录里的所有的go文件

FMT output format

The FMT Pack and the heap in the libc use printf, scanf,fprintf,fscanf very similar. The following things are not unfamiliar to C programmers.

Note: println is not supported, and printf supports the output of the% type:

package mainimport "fmt"import "math"func main() {    fmt.Println("hello world")    fmt.Printf("%t\n", 1==2)    fmt.Printf("二进制:%b\n", 255)    fmt.Printf("八进制:%o\n", 255)    fmt.Printf("十六进制:%X\n", 255)    fmt.Printf("十进制:%d\n", 255)    fmt.Printf("浮点数:%f\n", math.Pi)    fmt.Printf("字符串:%s\n", "hello world")}

Of course, you can also use the same control characters as the C language, such as \n\t\r

Variables and constants

Variables are declared much like JavaScript, using the var keyword. Note:Go is a static type of language , the following is the code:

//声明初始化一个变量var  x int = 100var str string = "hello world"</pre>//声明初始化多个变量var  i, j, k int = 1, 2, 3//不用指明类型,通过初始化值来推导var b = true //bool型

There is also a way to define variables (which reminds me of the Pascal language, but completely different)

x := 100 //等价于 var x int = 100;

Constants are simple, using the Const keyword:

const s string = "hello world"const pi float32 = 3.1415926

Array

Look directly at the code (note the For statement, and C very similar to it, there is no parentheses)

func main() {    var a [5]int    fmt.Println("array a:", a)    a[1] = 10    a[3] = 30    fmt.Println("assign:", a)    fmt.Println("len:", len(a))    b := [5]int{1, 2, 3, 4, 5}    fmt.Println("init:", b)    var c [2][3]int    for i := 0; i < 2; i++ {        for j := 0; j < 3; j++ {            c[i][j] = i + j        }    }    fmt.Println("2d: ", c)}

Operation Result:

array a: [0 0 0 0 0]assign: [0 10 0 30 0]len: 5init: [1 2 3 4 5]2d:  [[0 1 2] [1 2 3]]

Slicing operations on arrays

This is Python.

a := [5]int{1, 2, 3, 4, 5}b := a[2:4] // a[2] 和 a[3],但不包括a[4]fmt.Println(b)b = a[:4] // 从 a[0]到a[4],但不包括a[4]fmt.Println(b)b = a[2:] // 从 a[2]到a[4],且包括a[2]fmt.Println(b)

Branch Loop statements

If statement

NOTE: The IF statement has no parentheses and must have curly braces

//if 语句if x % 2 == 0 {    //...}//if - elseif x % 2 == 0 {    //偶数...} else {    //奇数...}//多分支if num < 0 {    //负数} else if num == 0 {    //零} else {    //正数}

Switch statement

NOTE: The switch statement has no break and can also use a comma case multiple values

switch i {    case 1:        fmt.Println("one")    case 2:        fmt.Println("two")    case 3:        fmt.Println("three")    case 4,5,6:        fmt.Println("four, five, six")    default:        fmt.Println("invalid value!")}

For statement

You've seen it before, and here's a look at the three forms of For: (Note: There is no while in the Go language)

//经典的for语句 init; condition; postfor i := 0; i<10; i++{     fmt.Println(i)}//精简的for语句 conditioni := 1for i<10 {    fmt.Println(i)    i++}//死循环的for语句 相当于for(;;)i :=1for {    if i>10 {        break    }    i++}

About semicolons

From the code above we can see that there is no semicolon in the code. In fact, like C, Go's formal syntax uses semicolons to terminate the statement. Unlike C, these semicolons are automatically inserted by the lexical analyzer in the process of scanning the source code using simple rules, so the input source code does not require a semicolon most of the time.

The rule is this: if the last token in front of a new line is an identifier (including int words like and float64 such), a basic value such as text, or one of the following tags, a semicolon is inserted automatically:

Break continue Fallthrough return + +--)}

Usually the Go program for uses semicolons only in circular statements to separate initializers, conditions, and increment cells. If you write multiple statements in a row, you also need to separate them with semicolons.

Note : You should not place the left brace of a control structure ( if , for , switch or select ) on the next line at any time. If you do this, a semicolon will be inserted in front of the curly braces, which may result in unwanted results .

Map

Map in other languages may be called hash table or called Dict, the following is the code related to map operation, the code is easy to understand

func main(){    m := make(map[string]int) //使用make创建一个空的map    m["one"] = 1    m["two"] = 2    m["three"] = 3    fmt.Println(m) //输出 map[three:3 two:2 one:1] (顺序在运行时可能不一样)    fmt.Println(len(m)) //输出 3    v := m["two"] //从map里取值    fmt.Println(v) // 输出 2    delete(m, "two")    fmt.Println(m) //输出 map[three:3 one:1]    m1 := map[string]int{"one": 1, "two": 2, "three": 3}    fmt.Println(m1) //输出 map[two:2 three:3 one:1] (顺序在运行时可能不一样)    for key, val := range m1{        fmt.Printf("%s => %d \n", key, val)        /*输出:(顺序在运行时可能不一样)            three => 3            one => 1            two => 2*/    }}

Pointer

Go language has pointers, see Code

var i int = 1var pInt *int = &i//输出:i=1     pInt=0xf8400371b0       *pInt=1fmt.Printf("i=%d\tpInt=%p\t*pInt=%d\n", i, pInt, *pInt)*pInt = 2//输出:i=2     pInt=0xf8400371b0       *pInt=2fmt.Printf("i=%d\tpInt=%p\t*pInt=%d\n", i, pInt, *pInt)i = 3//输出:i=3     pInt=0xf8400371b0       *pInt=3fmt.Printf("i=%d\tpInt=%p\t*pInt=%d\n", i, pInt, *pInt)

Go has two mechanisms for allocating memory, namely the built-in function new and make. They do things differently, they apply different types, which can cause confusion, but the rules are simple.

Memory allocation

New is a built-in function that allocates memory, but unlike the work of new in other languages with the same name, it simply zeroed out the memory instead of initializing the memory. New (t) assigns a zero-value storage space and returns the address, which is a value of type *t, to a project of type T. In the terms of Go, it returns a pointer to the newly assigned 0 value of type T .

make(T, args ) The purpose of the function is new(T) different. It is used only to create slices, maps, and Chan (message Pipelines) and returns T *T an initialized (not 0 ) instance of the type (not). This difference arises because these three types are essentially references to data structures that must be initialized before they are used. For example, a slice is a descriptor with three items of content, including pointers, lengths, and capacities that point to data (inside an array), and the slice value is before the three items are initialized nil . For slices, mappings, and channels, the make internal data structures are initialized and the values that will be used are prepared. Such as:

The following code assigns an integer array with a length of 10, a capacity of 100, and a slice that returns the first 10 arrays

make([]int, 10, 100)

The following example illustrates new the make difference.

var p *[]int = new([]int)   // 为切片结构分配内存;*p == nil;很少使用var v  []int = make([]int, 10) // 切片v现在是对一个新的有10个整数的数组的引用// 不必要地使问题复杂化:var p *[]int = new([]int)fmt.Println(p) //输出:&[]*p = make([]int, 10, 10)fmt.Println(p) //输出:&[0 0 0 0 0 0 0 0 0 0]fmt.Println((*p)[2]) //输出: 0// 习惯用法:v := make([]int, 10)fmt.Println(v) //输出:[0 0 0 0 0 0 0 0 0 0]

Function

To be honest, I'm a little bit dissatisfied with the go language, which in turn declares the variable type and the function return value (keeping the same as C?). Oh

package mainimport "fmt"func max(a int, b int) int { //注意参数和返回值是怎么声明的    if a > b {        return a    }    return b}func main(){    fmt.Println(max(4, 5))}

function returns multiple values

Many of the package in Go will return two values, one is normal and one is error, as follows:

package mainimport "fmt"func main(){    v, e := multi_ret("one")    fmt.Println(v,e) //输出 1 true    v, e = multi_ret("four")    fmt.Println(v,e) //输出 0 false    //通常的用法(注意分号后有e)    if v, e = multi_ret("four"); e {        // 正常返回    }else{        // 出错返回    }}func multi_ret(key string) (int, bool){    m := map[string]int{"one": 1, "two": 2, "three": 3}    var err bool    var val int    val, err = m[key]    return val, err}

Function indeterminate parameter

The example is clear, and I'm not going to say much.

func sum(nums ...int) {    fmt.Print(nums, " ")  //输出如 [1, 2, 3] 之类的数组    total := 0    for _, num := range nums { //要的是值而不是下标        total += num    }    fmt.Println(total)}func main() {    sum(1, 2)    sum(1, 2, 3)    //传数组    nums := []int{1, 2, 3, 4}    sum(nums...)}

function closures

Nextnum This function returns an anonymous function that remembers the value of I+j in Nextnum and changes the value of i,j, thus forming a closure usage

func nextNum() func() int {    i,j := 1,1    return func() int {        var tmp = i+j        i, j = j, tmp        return tmp    }}//main函数中是对nextNum的调用,其主要是打出下一个斐波拉契数func main(){    nextNumFunc := nextNum()    for i:=0; i<10; i++ {        fmt.Println(nextNumFunc())    }}

Recursion of functions

and c are basically the same

func fact(n int) int {    if n == 0 {        return 1    }    return n * fact(n-1)}func main() {    fmt.Println(fact(7))}

Structural body

The structure of Go is basically the same as C, but somewhat different during initialization, go supports initialization with a name.

type Person struct {    name string    age  int    email string}func main() {    //初始化    person := Person{"Tom", 30, "tom@gmail.com"}    person = Person{name:"Tom", age: 30, email:"tom@gmail.com"}    fmt.Println(person) //输出 {Tom 30 tom@gmail.com}    pPerson := &person    fmt.Println(pPerson) //输出 &{Tom 30 tom@gmail.com}    pPerson.age = 40    person.name = "Jerry"    fmt.Println(person) //输出 {Jerry 40 tom@gmail.com}}

Structure method

Don't say more, look at the code.

Note: There is no public, protected, or private keyword in the go language, so if you want a method to be accessible by another package, you need to capitalize the first letter of the method. This is a convention .

type rect struct {    width, height int}func (r *rect) area() int { //求面积    return r.width * r.height}func (r *rect) perimeter() int{ //求周长    return 2*(r.width + r.height)}func main() {    r := rect{width: 10, height: 15}    fmt.Println("面积: ", r.area())    fmt.Println("周长: ", r.perimeter())    rp := &r    fmt.Println("面积: ", rp.area())    fmt.Println("周长: ", rp.perimeter())}

Interfaces and polymorphic

Interface means polymorphic, here is a classic example, don't say more, look at the code yourself.

//---------- 接 口 --------//type shape interface {    area() float64 //计算面积    perimeter() float64 //计算周长}//--------- 长方形 ----------//type rect struct {    width, height float64}func (r *rect) area() float64 { //面积    return r.width * r.height}func (r *rect) perimeter() float64 { //周长    return 2*(r.width + r.height)}//----------- 圆  形 ----------//type circle struct {    radius float64}func (c *circle) area() float64 { //面积    return math.Pi * c.radius * c.radius}func (c *circle) perimeter() float64 { //周长    return 2 * math.Pi * c.radius}// ----------- 接口的使用 -----------//func interface_test() {    r := rect {width:2.9, height:4.8}    c := circle {radius:4.3}    s := []shape{&r, &c} //通过指针实现    for _, sh := range s {        fmt.Println(sh)        fmt.Println(sh.area())        fmt.Println(sh.perimeter())    }}

Error handling –error interface

Function error return is probably the most tangled thing in C + +, Go's multivalued return can make it easier for us to return an error, it can return a regular return value, but also easily returned a detailed error description. Typically, the error is in the wrong type, and it has a built-in interface.

type error interface {    Error() string}

Let's look at an example:

package mainimport "fmt"import "errors"//自定义的出错结构type myError struct {    arg  int    errMsg string}//实现Error接口func (e *myError) Error() string {    return fmt.Sprintf("%d - %s", e.arg, e.errMsg)}//两种出错func error_test(arg int) (int, error) {    if arg < 0  {         return -1, errors.New("Bad Arguments - negtive!")     }else if arg >256 {        return -1, &myError{arg, "Bad Arguments - too large!"}    }    return arg*arg, nil}//相关的测试func main() {    for _, i := range []int{-1, 4, 1000} {        if r, e := error_test(i); e != nil {            fmt.Println("failed:", e)        } else {            fmt.Println("success:", r)        }    }}

After running the program output:

failed: Bad Arguments - negtive!success: 16failed: 1000 - Bad Arguments - too large!

Error handling –defer

The following programs are unfamiliar to everyone who is familiar with the C language (problems with resource leaks), and C + + uses RAII to solve this problem.

func CopyFile(dstName, srcName string) (written int64, err error) {    src, err := os.Open(srcName)    if err != nil {        return    }    dst, err := os.Create(dstName)    if err != nil {        return    }    written, err = io.Copy(dst, src)    dst.Close()    src.Close()    return}

The go language introduces defer to ensure that files that are opened can be closed. As follows: (This solution is still more elegant)

func CopyFile(dstName, srcName string) (written int64, err error) {    src, err := os.Open(srcName)    if err != nil {        return    }    defer src.Close()    dst, err := os.Create(dstName)    if err != nil {        return    }    defer dst.Close()    return io.Copy(dst, src)}

Go's defer statement presets a function call (the deferred function), which runs immediately when the function executes defer returns. This method appears to be different from the conventional, but it is very effective to deal with the above situation, no matter how the function returns, must be the release of resources.

Let's look at an example of a defer function:

for i := 0; i < 5; i++ {    defer fmt.Printf("%d ", i)}

The deferred function executes in a last-in, first-out (LIFO) line, so the above code will print 4 3 2 1 0 on return.

In short, I personally feel that the function of defer is a bit strange, I have not fully figured out yet.

Error handling –panic/recover

For unrecoverable errors, go provides an built-in panic function that creates a run-time error and causes the program to stop (rather violent). The function receives an arbitrary type (often a string) to be printed when the program dies. When the compiler checks for a panic at the end of the function, it stops the regular return statement check.

The following is just an example. The actual library function should avoid panic. If the problem is tolerable, it is best to keep things going rather than terminating the entire program.

var user = os.Getenv("USER")func init() {    if user == "" {        panic("no value for $USER")    }}

When panic is called, it immediately stops execution of the current function and begins to step through the function stack, running all defer functions. If the undo reaches the top of the stack, the program dies. However, you can also use the built-in recover function to regain control of the go and return to normal execution. The call to recover notifies the undo stack and returns the parameters passed to the panic. Because only the code that runs during the undo is in a function that is defer, recover is only useful inside the deferred function.

You can simply understand that recover is used to capture Painc, preventing the program from hanging up all at once.

Here is a routine, very simple, does not explain

func g(i int) {    if i>1 {        fmt.Println("Panic!")        panic(fmt.Sprintf("%v", i))    }}func f() {    defer func() {        if r := recover(); r != nil {            fmt.Println("Recovered in f", r)        }    }()    for i := 0; i < 4; i++ {        fmt.Println("Calling g with ", i)        g(i)        fmt.Println("Returned normally from g.")     }}func main() {    f()    fmt.Println("Returned normally from f.")}

The result of the operation is as follows: (we can see that the for loop after Painc has not been executed, but the main program is still going down)

Calling g with  0Returned normally from g.Calling g with  1Returned normally from g.Calling g with  2Panic!Recovered in f 2Returned normally from f.

Are you used to this way of programming? I think it's a little weird. Oh.

Well, here is a go language-related programming grammar introduction, I do not have all the details, just to let you know what the go language look like. Of course, this is not the end, please look forward to the next--go language features .

(Reprint this site article please indicate the author and source cool shell –coolshell.cn, do not use for any commercial purposes)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.