Go语言入门【三】:通过一段代码学Go语法

写在前面

Golang的语法足够简单,但变化很多,刚接触只需要掌握典型的用法即可,不需要知道所有的语法糖,所以代码中并不会包含所有可能的语法形式。

并发是Golang的一大主题,后续有专门的一节,并不出现在这一节。

还有一些『约定』:

  • 可见性。Java中有private,protect,public。Golang默认采用首字母大小写来判断:首字母大写的变量、方法为public,所有范围内可见;首字母小写的为private,本文件内可见。
  • 简洁性。import引入的包以及定义的变量必须被使用,否则程序编译不通过。因此,代码var p ClassA不是一个声明定义,而是包含了初始化,实际上内存已经被分配了,这一点很容易忽视。

下面上代码:

//一段普通的Go语言代码,用于go语言学习,作者知米无忌于2016-11-29


//声明包,包名和目录的路径一致,以$GOPATH/src为根,如src/math/add.go的包为math。
// 此外,如果为入口(即包含main函数)则包名为main,此时可以被go build编译为可执行文件。
package main

//块状import注意:
//import必须被使用,不能import了但不用他
import (
    "fmt"
    "strconv"
    "reflect"
)

//块状定义变量
var (
    // int 类型包括了rune, int8, int16, int32, int64和byte, uint8, uint16, uint32, uint64。其中rune是int32的别称,byte是uint8的别称。
    myInt int
    //float 包括了float32,float64
    myFloat float32
    myBool bool
    myString string
)

//块状声明常量
const (
    constString = "hello world,世界"
)

// 全局单独定义的变量
var globalDefinedVar interface{}

// 定义一个结构体(也是类,因为golang没有类的概念),面向对象
type person struct {
    name string
    age  int
}

//person 的成员函数,显式的指定p,即Java中的this指针,python中的函数第一个参数self
func (p *person)  introduceMyself() {
    fmt.Println("my name is " + p.name)
    fmt.Println(p.age)
}
func (p *person) shoot() {
    fmt.Println("I can shoot, so I can play football.")
}

//定义一个接口
type footballPlayer interface {
    shoot()
}

func main() {

    ////////////
    // 1.变量定义
    ////////////

    var localString string
    localString = `字符串是
    一对双引号(表示单行)或反引号(表示多行)
    括起来定义`


    ////////////
    // 2.rune, byte数组,string的关系
    ////////////

    myRune := '我'
    fmt.Println(myRune)
    //rune转为string
    myRuneString:= string(myRune)
    fmt.Println(myRuneString)
    //rune转为字节数组
    bytes:=[]byte(myRuneString)
    fmt.Println(bytes)


    // interface{} 类型可赋值任意类型,类似Java的Object类型
    globalDefinedVar = localString

    newVar := ":=是声明并初始化的简写形式,由系统自动推测类型"
    fmt.Println(newVar)

    ////////////
    // 3.数组定义并初始化
    ////////////

    myArray := [3]int{1, 2, 3}
    //数组定义,默认初始化为了5个0
    var myArray2 [5]int
    fmt.Println(myArray2)
    fmt.Println(myArray)

    ////////////
    // 4.slice
    ////////////

    mySlice := []int{1, 2, 3, 4}
    //从数组创建slice,注意1:的使用方式,从第一个元素取到末尾,还可以[1:4]从第一个取到第四个(不包含)。来自于python(作者注)
    mySlice2 := myArray[1:]
    mySlice=append(mySlice,5,6,7)

    ////////////
    // 5.if,else块没什么特殊,myBool未定义默认为false,执行else
    ////////////

    if myBool {
        fmt.Println("if")
    } else {
        fmt.Println("else")
    }

    ////////////
    // 6.for 循环
    ////////////
    for index, value := range mySlice {
        fmt.Printf("index: %d,value:%d \n", index, value)
    }
    for (true) {
        fmt.Println("还可以这样使用,相当于while(true)")
        //避免无限循环,直接break掉
        break
    }

    ////////////
    // 7.map创建,删除和使用,range关键字使用
    ////////////

    myMap := make(map[string]int)
    myMap["a"] = 1
    myMap["b"] = 2
    myMap["c"] = 3
    delete(myMap, "a")
    for key, value := range myMap {
        fmt.Printf("key: %s,value:%d", key, value)
    }

    ////////////
    // 8.面向对象
    ////////////

    // 对象初始化的两种方式,第一种返回的是指针,第二种返回的是对象。
    //注意new永远返回指针
    jack := new(person)
    jack.name = "jack"
    jack.age = 17
    amy := person{"amy", 16}
    jack.introduceMyself()
    //证明是指针
    (*jack).introduceMyself()
    amy.introduceMyself()
    //抛异常 invalid indirect of amy (type person)
    //(*amy).introduceMyself()
    fmt.Println(reflect.TypeOf(jack))
    fmt.Println(reflect.TypeOf(amy))



    ////////////
    // 9.接口使用
    ////////////

    //接口的赋值,可以看出来不需要jack的person类实现该接口就可以实现,只需要拥有接口所需的功能即可。
    var footballPlayer1 = jack
    footballPlayer1.shoot()

    //函数调用,可以多返回值
    myString = "golang is awesome"
    myRet1, myRet2 := receive2Return2(myString, myInt)
    fmt.Println(myRet1, myRet2)



    ////////////
    // 10.异常处理
    ////////////

    //错误处理,调用了一个抛异常的方法
    malfunction()
    //两个知识点:
    //1.recover会收集到由调用栈中的panic抛出的异常信息
    //2.defer的执行时机是执行defer的函数退出的时候,类似于java中的finally,但是不需要把一大段代码用大括号包围,这样代码层次减少了。
    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()

    //每个定义过的变量和常量都要被使用,不允许垃圾存在,这里做个打印
    fmt.Println(myBool, myFloat,constString,mySlice2)

}

func receive2Return2(param1 string, param2 int) (ret1 string, ret2 int) {
    fmt.Println("param1:" + param1)
    fmt.Println("param2:" + strconv.Itoa(param2))
    return "returned " + param1, param2 + 1
}

func malfunction() {
    panic("some thing went wrong!")
}
    原文作者:纳达丶无忌
    原文地址: https://www.jianshu.com/p/b7332a40a11d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞