go study notes the particular concern of what basic grammar

In the last article, we personally wrote the first hands- Golanguage version Hello World, and meet the Goconstant language interesting variables and restless.

I believe that through Fibonacci number on the articles that you have initially mastered the Gosimilarities and differences between the language of variables and constants and other major programming languages, in order to better learn and master the following Gobasic syntax, the following briefly recap variable and constant knowledge.

Interestingly, variables and constants restless

  • The default value of zero variable initialization
func TestVariableZeroValue(t *testing.T) {
    var a int
    var s string

    // 0
    t.Log(a, s)
    // 0 ""
    t.Logf("%d %q", a, s)
}

intType variable initialization default value of zero is zero 0, stringthe type of the variable value is initialized to zero by default is an empty string `, other types have a corresponding zero value.

  • You can assign multiple variables simultaneously
func TestVariableInitialValue(t *testing.T) {
    var a, b int = 1, 2
    var s string = "hello Go"

    // 1 2 hello Go
    t.Log(a, b, s)
}

Most other major programming languages support multiple variables are initialized, but there are very few like Golanguage so that not only supports simultaneous initialization, you can also assign the same time.

  • A number of variables you can use parentheses ()uniform definition
func TestVariableShorter(t *testing.T) {
    var (
        a int    = 1
        b int    = 2
        s string = "hello go"
    )

    // 1 2 hello Go
    t.Log(a, b, s)
}

With parentheses ()way, omitted the same varkeywords, it seems more unified

  • Variable type can be automatically inferred
func TestVariableTypeDeduction(t *testing.T) {
    var a, b, s = 1, 2, "hello Go"

    // 1 2 hello Go
    t.Log(a, b, s)
}

GoThe language can be speculated that the variable value of the variable type, variable type may be omitted, again simplifying the definition of the variables, but the variable type is still strongly typed, not as Jsweak as type.

  • Variables can be used :=in the form of more simplified
func TestVariableTypeDeductionShorter(t *testing.T) {
    a, b, s := 1, 2, "hello Go"

    // 1 2 hello Go
    t.Log(a, b, s)

    s = "hello golang"

    // 1 2 hello golang
    t.Log(a, b, s)
}

Keywords omitted varin favor of using :=symbols declare and initialize a variable value and further simplifies the use of automatic variables are defined type inference capability, can not be used again when the assignment :=symbol.

  • Variable vardeclaration scope is greater than the variable :=declaration
var globalTestId = 2
// globalTestName := "type_test" is not supported
var globalTestName = "type_test"

func TestVariableScope(t *testing.T) {
    // 2 type_test
    t.Log(globalTestId, globalTestName)

    globalTestName = "TestVariableScope"

    // 2 TestVariableScope
    t.Log(globalTestId, globalTestName)
}

varVariables can be declared outside the function or role within a function, and :=variable declarations can only function in the role, Goand there is no concept of global variables, variable scope of the package only for purposes.

  • Use variables and constants of the same
func TestConstant(t *testing.T) {
    const a, b = 3, 4
    const s = "hello Go"

    // 3 4 hello Go
    t.Log(a, b, s)
}

Constant declaration keyword constconsistent use, constants and variables, with the ability to type inference, there are several constants defined in simplified form.

  • Although there is no enumerated type, but can be used iotawith the enumeration constants to achieve
func TestConstant2Enum(t *testing.T) {
    const (
        java = iota
        golang
        cpp
        python
        javascript
    )
    // 0 1 2 3 4
    t.Log(java, golang,cpp,python,javascript)
}

iotaThe first time appeared in a set of constants defined in its value 0, when applied to the next constant whose value is increased from the beginning 1, met again iotarestored 0. Much like the effect forloop index cycle i, obviously is a constant, but why play out taste of variables, and I think iotathe reason restless.

  • Constant iotahas magical, arithmetic, and bit
func TestConstantIotaBitCalculate(t *testing.T){
    const (
        Readable = 1 << iota
        Writable
        Executable
    )
    // 0001 0010 0100 即 1 2 4
    t.Log(Readable, Writable, Executable)

    // 0111 即 7,表示可读,可写,可执行
    accessCode := 7
    t.Log(accessCode&Readable == Readable, accessCode&Writable == Writable, accessCode&Executable == Executable)
}

Defined bits LSB 1when expressed readable, the left one represents write, and left two executable representation, in accordance with the bit arithmetic logic, if the target permission bits have read permission, and at this time reading constants bitwise operation result after must be readable, shows, iotavery suitable for such operations.

Overall, the Golanguage is very interesting variables, constants, iotanot so law-abiding, not difficult to see from the above summarized, the Golanguage and other popular programming languages have a lot of different, learning to focus on the special.

If you want to review this section, knowledge can be concerned about the public No. [Snow Dream Inn technology] to find interesting variables and constants go restless study notes the article to view it.

Simple type in a special care complex

Learning Gowhen variables and constants language, although not specifically emphasized the type of a variable or constant, but the type most programming languages are basically about the same, after all, in which the real world is the same thing!

Just a guess, it is not enough, now we have to comb it again Gothe type of language which, and other mainstream programming languages have different compared to what?

Go Variable type of language can be divided into the following categories:

  • bool

Boolean bool, true and false representationtrue|false

  • (u)int ,(u)int8 , (u)int16, (u)int32,(u)int64,uintptr

intIt represents an integer type, while the number of bits does not mean without no bits, 32when the bit length of the operating system 32bit, 64when the bit length of the operating system of 64bits. The last uintptrtype of pointer.

  • byte(uint8) ,rune(int32),string

byteByte type, is uint8an alias, and runeis Gothe character type is int32an alias.

  • float32 ,float64 ,complex64 ,complex128

Only floatthe type of decimal representation, there is no doubletype, the less the more simple types for developers, is not it? complex64=float32+float32Is a complex type, yes! The complex is on the high school math books, 3+4ithat strange figure!

Go The type is relatively simple, integer, decimal, plural, bytes, characters and boolean types, the same kind of type did not continue to subdivide different names but are named according to the type of direct length, this can be very intuitive, see the name known meaning, according to the data size of the direct selection of the type, does not cost the brain!

As a general-purpose programming language, Gobuilt-in types in special care actually a complex of this type of mathematical concepts, is an interesting thing, is not meant to Godo a better job in engineering projects? Like Gonatural support concurrent Like ?

Since one of the few types of special care the type complex, then we simply use under a complex type, after all other types and other mainstream programming languages ​​or less.

func TestComplex(t *testing.T) {
    c := 3 + 4i

    // 5
    t.Log(cmplx.Abs(c))
}

Life is short, direct use of the variable type inference simplified variable declaration, the type of complex obtained cmodulus (absolute value)

Since learning the complex, how can less got Euler's formula, after all, is the "world's most beautiful formula", just use the knowledge of the complex, then we simply to test it!

go-base-grammar-complex-euler.png

func TestEuler(t *testing.T) {
    // (0+1.2246467991473515e-16i)
    t.Log(cmplx.Pow(math.E, 1i*math.Pi) + 1)

    // (0+1.2246467991473515e-16i)
    t.Log(cmplx.Exp(1i*math.Pi) + 1)

    // (0.000+0.000i)
    t.Logf("%.3f", cmplx.Exp(1i*math.Pi)+1)
}

Because of the complex complexis to use a floattype of representation, and floattype no matter what programming languages are not accurate, so the results of Euler's formula is very, very close to zero, when after only three decimal places, the calculation result is (0.000+0.000i), plural mold is 0, so far verified the Euler equations.

Or to read the complex characteristics of the type of research

The plural is important, but other types are also very important to find out about the simple knowledge of the complex, we still want to focus on research into these types of built-in or special about these types Overall, compared to other mainstream What programming language similarities and differences.

  • Only display type conversion, an implicit type conversion absent
func TestExplicitTypeConvert(t *testing.T) {
    var a, b int = 3, 4
    var c int
    c = int(math.Sqrt(float64(a*a + b*b)))

    // 3 4 5
    t.Log(a, b, c)
}

Two right-angle edge of known Pythagorean hypotenuse, obtained according to the Pythagorean theorem, and the sum of the squares of side length i.e. longer square root length of the hypotenuse, however, math.Sqrtthe method of receiving float64type, also return float64type, the actual value of the full is a inttype, and no automatic type conversion in this case, can only be cast to get our expectations, this is the display type conversion.

  • Alias ​​Type can not be performed and the type of the original implicit type conversion
func TestImplicitTypeConvert2(t *testing.T) {
    type MyInt64 int64

    var a int64 = 1
    var b MyInt64

    // b = a : cannot use a (type int64) as type MyInt64 in assignment
    b = MyInt64(a)
    t.Log(a, b)
}

MyInt64It is int64the alias, the type band the original type acan not be nor implicit type conversion, being given cannot use a (type int64) as type MyInt64 in assignmentonly for display type conversion.

  • Pointer type supports, but does not support any form of computing
func TestPointer(t *testing.T) {
    var a int = 1
    var pa *int = &a

    // 0xc0000921d0 1 1
    t.Log(pa, *pa, a)

    *pa = 2

    // 0xc0000901d0 2 2
    t.Log(pa, *pa, a)
}

Similarly, the pointer type is in turn written in other programming languages, but personally feel this is good, pointing to intthe type of pointer *int, &aa variable amemory address, the variable padeposit is variable aaddress, *pajust that is a variable avalue.

The example above shows the type of a variable declared but not used to Gotype inference ability, not the ability to put in that use is simply a waste, it provides a shorter way to rewrite the above example, and the last part of the way to explain: "Pointer type does not support any form of computing. "


func TestPointerShorter(t *testing.T) {
    a := 1
    pa := &a

    // 0xc0000e6010 1 1
    t.Log(pa, *pa, a)

    *pa = 2

    // 0xc0000e6010 2 2
    t.Log(pa, *pa, a)

    // pa = pa + 1 : invalid operation: pa + 1 (mismatched types *int and int)
    //pa = pa + 1

    // *int int int
    t.Logf("%T %T %T", pa, *pa,a)
}

Variable pais a pointer type, memory is the memory address of a variable, only a distance not fondle, *pais the value of the pointer is pointing variables can be modified, of course, no problem as you can re-assign variables athe same, but the pointer pais not can any form of operation, pa = pa + 1it will error invalid operation.

Guess there are no eggs operators to manipulate it

Variables and types just an isolated declaration, no calculation is not logical, not all programs are predefined variables, Gooperators are simple or complex, let us see for yourself!

  • Arithmetic operators less ++iand--i
func TestArithmeticOperator(t *testing.T) {
    a := 0
    // 0
    t.Log(a)

    a = a + 1
    // 1
    t.Log(a)

    a = a * 2
    // 2
    t.Log(a)

    a = a % 2
    // 0
    t.Log(a)

    a++
    // 1
    t.Log(a)
}

It supports most normal operator, does not support the pre-increment, pre-decrement, and this is a good thing, never made a mistake i++and ++ioperational results matter, because there is not support ++i!

  • There are tricks for equality comparison operators
func TestComparisonOperator(t *testing.T) {
    a, b := 0, 1
    t.Log(a, b)

    // false true true
    t.Log(a > b, a < b, a != b)
}

Greater than, less than, not equal to such a relationship is normal, Golangwe did not play new tricks, and other mainstream programming language, like logic, do not particularly care about. But on comparing arrays ==, Goindicate there is something to say!

Go The array can be compared, and when the number of dimensions of the array elements of the two arrays to be compared are the same, consistent with the sequence and two array elements are the same, two equal arrays, while other programming languages ​​in general mainstream For an array of references are compared, so it needs special attention.

func TestCompareArray(t *testing.T) {
    a := [...]int{1, 2, 3}
    //b := [...]int{2, 4}
    c := [...]int{1, 2, 3}
    d := [...]int{1, 2, 4}

    // a == b --> invalid operation: a == b (mismatched types [3]int and [2]int)
    //t.Log(a == b)

    // true false
    t.Log(a == c,a == d)
}

Arrays aand care one-dimensional array and the number of elements is 3thus equal to two arrays can be compared and, if the array aand bcomparing the error invalid operation, because the number of elements in the two arrays are not the same, can not be compared!

  • Logical operators honest part no abnormality
func TestLogicalOperator(t *testing.T) {
    a, b := true, false
    t.Log(a, b)

    // false true false true
    t.Log(a&&b,a||b,!a,!b)
}
  • Bit by bit new operators cleared &^very clever

GoLanguage defined bit is cleared by the operator is &^calculated as follows the law:

When the right of the median operation 1time, the operation is whether it is left 1or 0the results are 0;
when the right digits for the operation 0, the result left the same operation digits.

func TestClearZeroOperator(t *testing.T) {
    // 0 0 1 0
    t.Log(1&^1, 0&^1, 1&^0, 0&^1)
}

I do not know still remember, in the constant introduction iotatime, had to file permissions, for example, to determine whether a given authorization code has a specific permission, is also given authorization code, how to revoke specific permissions it?

func TestClearZeroOperator(t *testing.T) {
    const (
        Readable = 1 << iota
        Writable
        Executable
    )
    // 0001 0010 0100 即 1 2 4
    t.Log(Readable, Writable, Executable)

    // 0111 即 7,表示可读,可写,可执行
    accessCode := 7
    t.Log(accessCode&Readable == Readable, accessCode&Writable == Writable, accessCode&Executable == Executable)

    // 0111 &^ 0001 = 0110 即清除可读权限
    accessCode = accessCode &^ Readable
    t.Log(accessCode&Readable == Readable, accessCode&Writing == Writing, accessCode&Executable == Executable)
}

accessCode = accessCode &^ ReadableBitwise operations cleared after losing the read permission, accessCode&Readable == Readablethere is no read permission when a judge again.

Flow control statements also have their own playfully

if Have something to say

With the addition of variable types and various operators realize now simple statement is not a problem, if the auxiliary flow control statements, then the realization of more complex sentence has a certain logic can be a higher level.

GoLanguage ifsemantics conditional statements and other mainstream programming language is the same, not the same as writing has its own rules and features on some of the details.

  • The conditional expression does not need parentheses ()
func TestIfCondition(t *testing.T) {
    for i := 0; i < 10; i++ {
        if i%2 == 0 {
            t.Log(i)
        }
    }
}

GoVarious forms of the language makes it very simple omission on the whole, but also allows developers to have other mainstream programming language is not used to when the initial contact, the end of the statement without a semicolon ;, conditional expressions without parentheses ()so the details, if not IDEautomatic prompts, these details are sure to spend a lot of time.

  • Conditional expression can define a variable, as long as the final result is a Boolean expression can
func TestIfConditionMultiReturnValue(t *testing.T) {
    const filename = "test.txt"
    if content, err := ioutil.ReadFile(filename); err != nil {
        t.Log(err)
    } else {
        t.Logf("%s\n", content)
    }
}

GoMultiple language support function return values, and then elaborate on this point later on, ioutil.ReadFilethe function returns an error message and file contents, when there is an error message err != nil, output an error message, otherwise the output file contents.

  • Variable conditional expressions defined in the scope is limited to the current statement block

go-base-grammar-if-scope.png

If you try to ifaccess the variable outside a block of statements content, the errorundefined: content

switch Not to be outdone

Compared to other mainstream programming languages, switchstatements biggest feature is the multiple caseis not required break, Goit will automatically break, which is very user-friendly.

  • switchAutomatically break, unlessfallthrough
func TestSwitchCondition(t *testing.T) {
    switch os := runtime.GOOS; os {
    case "darwin":
        t.Log("Mac")
    case "linux":
        t.Log("Linux")
    case "windows":
        t.Log("Windows")
    default:
        t.Log(os)
    }
}
  • Conditional expression is not limited to constant or integer

Other mainstream programming language in switchthe conditional expression only supports a limited type, there are some limitations of use, Gothe language is different, this change is also very interesting, the use of switchdo not worry about the variable type when making branch control!

  • caseLanguage support for a variety of conditions, comma ,separated, or logic
func TestSwitchMultiCase(t *testing.T) {
    for i := 0; i < 10; i++ {
        switch i {
        case 0, 2, 4, 6, 8, 10:
            t.Log("Even", i)
        case 1, 3, 5, 7, 9:
            t.Log("odd", i)
        default:
            t.Log("default", i)
        }
    }
}
  • Omitted switchwhen the conditional expressions, switchlogic and a plurality of if elselogic same
func TestSwitchCaseCondition(t *testing.T) {
    for i := 0; i < 10; i++ {
        switch {
        case i%2 == 0:
            t.Log("Even", i)
        case i%2 == 1:
            t.Log("odd", i)
        default:
            t.Log("default", i)
        }
    }
}

for Late

最后登场的是 for 循环,一个人完成了其他主流编程语言三个人的工作,Go 语言中既没有 while 循环也,也没有 do while 循环,有的只是 for 循环.

  • 循环条件不需要小括号 ()
func TestForLoop(t *testing.T) {
    sum := 0
    for i := 1; i <= 100; i++ {
        sum += i
    }
    // 1+2+3+...+99+100=5050
    t.Log(sum)
}

再一次看到条件表达式不需要小括号 () 应该不会惊讶了吧? if 的条件语句表达式也是类似的,目前为止,接触到明确需要小括号的 () 也只有变量或常量定义时省略形式了.

  • 可以省略初始条件
func convert2Binary(n int) string {
    result := ""
    for ; n > 0; n /= 2 {
        lsb := n % 2
        result = strconv.Itoa(lsb) + result
    }
    return result
}

func TestConvert2Binary(t *testing.T) {
    // 1 100 101 1101
    t.Log(
        convert2Binary(1),
        convert2Binary(4),
        convert2Binary(5),
        convert2Binary(13),
    )
}

利用整数相除法,不断取余相除,得到给定整数的二进制字符串,这里就省略了初始条件,只有结束条件和递增表达式.这种写法同样在其他主流的编程语言是没有的,体现了 Go 设计的简洁性,这种特性在以后的编程中会越来越多的用到,既然可以省略初始条件,相信你也能猜到可不可以省略其他两个条件呢?

  • 可以省略初始条件和递增表达式
func printFile(filename string) {
    if file, err := os.Open(filename); err != nil {
        panic(err)
    } else {
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
            fmt.Println(scanner.Text())
        }
    }
}

func TestPrintFile(t *testing.T) {
    const filename = "test.txt"
    printFile(filename)
}

打开文件并逐行读取内容,其中 scanner.Scan() 的返回值类型是 bool,这里省略了循环的初始条件和递增表达式,只有循环的终止条件,也顺便实现了 while 循环的效果.

  • 初始条件,终止条件和递增表达式可以全部省略
func forever() {
    for {
        fmt.Println("hello go")
    }
}

func TestForever(t *testing.T) {
    forever()
}

for 循环中没有任何表达式,意味着这是一个死循环,常用于 Web 请求中监控服务端口,是不是比 while(true) 要更加简单?

压轴的一等公民函数隆重登场

虽然没有特意强制函数,但是示例代码中全部都是以函数形式给出的,函数是封装的一种形式,更是 Go 语言的一等公民.

  • 返回值在函数声明的最后,多个返回值时用小括号 ()
func eval(a, b int, op string) int {
    var result int
    switch op {
    case "+":
        result = a + b
    case "-":
        result = a - b
    case "*":
        result = a * b
    case "/":
        result = a / b
    default:
        panic("unsupported operator: " + op)
    }
    return result
}

func TestEval(t *testing.T) {
    t.Log(
        eval(1, 2, "+"),
        eval(1, 2, "-"),
        eval(1, 2, "*"),
        eval(1, 2, "/"),
        //eval(1, 2, "%"),
    )
}

不论是变量的定义还是函数的定义,Go 总是和其他主流的编程语言相反,个人觉得挺符合思维顺序,毕竟都是先有输入才能输出,多个输出当然要统一隔离在一块了.

  • 可以有零个或一个或多个返回值
func divide(a, b int) (int, int) {
    return a / b, a % b
}

func TestDivide(t *testing.T) {
    // 2 1
    t.Log(divide(5, 2))
}

小学时就知道两个整数相除,除不尽的情况下还有余数.只不过编程中商和余数都是分别计算的,Go 语言支持返回多个结果,终于可以实现小学除法了!

  • 返回多个结果时可以给返回值起名字

func divideReturnName(a, b int) (q, r int) {
    return a / b, a % b
}

func TestDivideReturnName(t *testing.T) {
    q, r := divideReturnName(5, 2)

    // 2 1
    t.Log(q, r)
}

还是整数除法的示例,只不过给返回值起了变量名称 (q, r int),但这并不影响调用者,某些 IDE 可能会基于次特性自动进行代码补全,调用者接收时的变量名不一定非要是 q,r .

  • 其他函数可以作为当前函数的参数
func apply(op func(int, int) int, a, b int) int {
    p := reflect.ValueOf(op).Pointer()
    opName := runtime.FuncForPC(p).Name()

    fmt.Printf("Calling function %s with args (%d,%d)\n", opName, a, b)
    return op(a, b)
}

func pow(a, b int) int {
    return int(math.Pow(float64(a), float64(b)))
}

func TestApply(t *testing.T) {
    // 1
    t.Log(apply(func(a int, b int) int {
        return a % b
    }, 5, 2))

    // 25
    t.Log(apply(pow, 5, 2))
}

apply 函数的第一个参数是 op 函数,第二,第三个参数是 int 类型的 a,b.其中 op 函数也接收两个 int 参数,返回一个 int 结果,因此 apply 函数的功能就是将 a,b 参数传递给 op 函数去执行,这种方式比 switch 固定运算类型要灵活方便!

  • 没有默认参数,可选参数等复杂概念,只有可变参数列表
func sum(numbers ...int) int {
    result := 0
    for i := range numbers {
        result += numbers[i]
    }
    return result
}

func TestSum(t *testing.T) {
    // 15
    t.Log(sum(1, 2, 3, 4, 5))
}

range 遍历方式后续再说,这里可以简单理解为其他主流编程语言中的 foreach 循环,一般包括当前循环索引和循环项.

指针类型很方便同时也很简单

Go 的语言整体上比较简单,没有太多花里胡哨的语法,稍微有点特殊的当属变量的定义方式了,由于具备类型推断能力,定义变量的方式有点多,反而觉得选择困难症,不知道这种情况后续会不会有所改变?

Go 语言的为数不多的类型中就有指针类型,指针本来是 c 语言的概念,其他主流的编程语言也有类似的概念,可能不叫做指针而是引用,但 Go 语言的发展和 c++ 有一定关系,保留了指针的概念.

但是这并不意味着 Go 语言的指针像 C 语言那样复杂,相反,Go 语言的指针很方便也很简单,方便是由于提供我们操作内存地址的方式,简单是因为不能对指针做任何运算!

简单回忆一下指针的基本使用方法:

func TestPointerShorter(t *testing.T) {
    a := 1
    pa := &a

    // 0xc0000e6010 1 1
    t.Log(pa, *pa, a)

    *pa = 2

    // 0xc0000e6010 2 2
    t.Log(pa, *pa, a)

    // pa = pa + 1 : invalid operation: pa + 1 (mismatched types *int and int)
    //pa = pa + 1

    // *int int int
    t.Logf("%T %T %T", pa, *pa,a)
}

& 可以获取变量的指针类型,* 指向变量,但不可以对指针进行运算,所以指针很简单!

当指针类型和其他类型和函数一起发生化学反应时,我们可能更加关心参数传递问题,其他主流的编程语言可能有值传递和引用传递两种方式,Go 语言进行参数传递时又是如何表现的呢?

func swapByVal(a, b int) {
    a, b = b, a
}

func TestSwapByVal(t *testing.T) {
    a, b := 3, 4

    swapByVal(a, b)

    // 3 4
    t.Log(a, b)
}

swapByVal 函数内部实现了变量交换的逻辑,但外部函数 TestSwapByVal 调用后变量 a,b 并没有改变,可见 Go 语言这种参数传递是值传递而不是引用传递.

上面示例中参数传递的类型都是普通类型,如果参数是指针类型的话,结果会不会不一样呢?

func swapByRef(a, b *int) {
    *a, *b = *b, *a
}

func TestSwapByRef(t *testing.T) {
    a, b := 3, 4

    swapByRef(&a, &b)

    // 4 3
    t.Log(a, b)
}

指针类型进行参数传递时可以交换变量的值,拷贝的是内存地址,更改内存地址的指向实现了原始变量的交换,参数传递的仍然是值类型.

实际上,Go 语言进行参数传递的只有值类型一种,这一点不像其他主流的编程语言那样可能既存在值类型又存在引用类型.

既然是值类型进行参数传递,也就意味着参数传递时直接拷贝一份变量供函数调用,函数内部如何修改参数并不会影响到调用者的原始数据.

如果只是简单类型并且不希望参数值被修改,那最好不过,如果希望参数值被修改呢?那只能像上例那样传递指针类型.

简单类型不论是传递普通类型还是指针类型,变量的拷贝过程不会太耗费内存也不会影响状态.

如果传递的参数本身是比较复杂的类型,仍然进行变量拷贝过程估计就不能满足特定需求了,可能会设计成出传递复杂对象的某种内部指针,不然真的要进行值传递,那还怎么玩?

Go 只有值传递一种方式,虽然简单,但实际中如何使用应该有特殊技巧,以后再具体分析,现在回到交换变量的例子,换一种思路.

func swap(a, b int) (int, int) {
    return b, a
}

func TestSwap(t *testing.T) {
    a, b := 3, 4

    a, b = swap(a, b)

    // 4 3
    t.Log(a, b)
}

利用 Go 函数可以返回多个值特性,返回交换后的变量值,调用者接收时相当于重新赋值,比传递指针类型要简单不少!

基础语法知识总结和下文预告

刚刚接触 Go 语言时觉得 Go 的语言很简单也很特别,和其他主流的编程语言相比,有着自己独特的想法.

语句结束不用分号 ; 而是直接回车换行,这一点有些不习惯,好在强大的 IDE 可以纠正这些细节.

变量声明时变量名在前,变量类型在后,可能更加符合大脑思维,但是习惯了先写变量类型再写变量名,这确实有一定程度的不方便,后来索性不写变量类型,自然就没有问题了.

函数声明同变量声明类似,返回值放到了最后部分,并且还可以有多个返回值,经过了变量的洗礼,再熟悉函数的这一特点也就不那么惊讶了,先输入后输出,想一想也有道理,难道其他编程语言的顺序都是错的?

接下来就是语法的细节,比如 if 的条件表达式可以进行变量赋值,switch 表达式可以不用 break,只有 for 循环一种形式等等.

这些细节总体来说比较简单方便,不用关心细节,放心大胆使用,从而专注于业务逻辑,等到语法不对时,IDE 自然会给出相应的报错提醒,放心大胆 Go !

This paper introduces the Gobasic syntax and other mainstream programming languages and the similarities and differences, you Getthere yet?

Below began to introduce Gobuilt-in container types, arrays, slices, Mapcome again!

Welcome to study together the exchange, if inappropriate, urge correction, for complete source code, please the public No. [Snow Dream Inn technology] message reply, thank you for your comment and forwarding!

Snow Dream Inn technology .png

Guess you like

Origin www.cnblogs.com/snowdreams1006/p/11368166.html