写在前面
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!")
}