Go 语言极速入门2 - 基础语法

一、变量定义

四种姿势

  • 完全体:var name type
  • 类型推断:var name = value
  • 最简体:name := value(仅用于函数内变量,包内变量不行)
  • 变量聚合定义:var( name1=value1 name2=value2 )
package main

import "fmt"

// 定义包内变量
var (
    aa = 1
    bb = "tianya"
)

// 定义变量,只使用默认初值
func variableZeroValue()  {
    var a int       // 0
    var s string    // ""
    var b bool      // false
    fmt.Println(a, s, b)
}

// 定义变量,赋初值
func variableInitialValue()  {
    var a, b int = 1, 2
    b = 3
    var s string = "haha"
    fmt.Println(a, b, s)
}

// 类型推断
func variableTypeDeduction()  {
    var a, b, c, d  = 1, 2, true, "hi"
    fmt.Println(a, b, c, d)
}

// 最简定义变量方式
func variableShorter() {
    a, b, c, d := 3, 2, true, "hi"
    fmt.Println(a, b, c, d)
}

func main() {
    variableZeroValue()
    variableInitialValue()
    variableTypeDeduction()
    variableShorter()
    fmt.Println(aa, bb)
}

二、内建变量类型

8 类(指针单独划了出来)

  • bool
  • string
  • (u)int、(u)int8、(u)int16、(u)int32、(u)int64
  • uintptr 指针
  • byte
  • rune 字符型,32 位,类比 char
  • float32、float64
  • complex32、complex64 复数 i = √-1

注意:类型转换必须强制转,转化成的类型可以不带小括号,如下

// 强制类型转换
func triangle()  {
    var a, b int = 3, 4
    var c int
    // float64 和 int 可以不加小括号,也可以加上
    // 开方内建函数定义:func Sqrt(x float64) float64
    c = int(math.Sqrt(float64(a*a + b*b)))
    fmt.Println(c)
}

三、常量与枚举

  • 常量定义姿势(常量必须有 value
  • 完全体:const name type = value
  • 后续的使用自动补类型:const name = value
  • 枚举定义姿势(Go 没有枚举,用 const 块来定义)
  • 自定义枚举:const ( name1=value1 name2=value2 )
  • iota 表达式枚举:const ( name1=iota表达式 name2 )
// 常量
func consts() {
    // 指定类型
    const filename string = "filename-const"
    // 不指定类型,表示类型不定
    const a, b = 3, 4
    var c int
    // 由于类型不定,所以这里不需要强转,如果定义为 const a, b int = 3, 4,则需要强转
    c = int(math.Sqrt(a*a + b*b))
    fmt.Println(filename, a, b, c)
}

// 枚举
func enums() {
    // 使用 const 块来实现枚举
    const (
        java = 0
        cpp  = 1
        c    = 2
    )
    fmt.Println(java, cpp, c) // 0 1 2
    // 使用 iota 块来实现自增枚举
    const (
        java1 = iota
        cpp1  
        c1    
    )
    fmt.Println(java1, cpp1, c1) // 0 1 2
}

四、条件语句

if:变量可以定义在 if 块内,其作用域就只在 if 块内了

import (
    "io/ioutil"
    "fmt"
)

func readFile() {
    const filename = "abc.txt"
    // Go 函数可以返回两个值
    // func ReadFile(filename string) ([]byte, error)
    contents, err := ioutil.ReadFile(filename)
    if err != nil {
        fmt.Println(err)
    } else {
        // contents 是 []byte, 用%s 可以打印出来
        fmt.Printf("%s", contents)
    }
    // if 语句外部可访问
    fmt.Printf("%s", contents)
}

func readFileShorter() {
    const filename = "abc.txt"
    // Go 函数可以返回两个值
    // func ReadFile(filename string) ([]byte, error)

    if contents, err := ioutil.ReadFile(filename); err != nil {
        fmt.Println(err)
    } else {
        // contents 是 []byte, 用%s 可以打印出来
        fmt.Printf("%s", contents)
    }
    // if 语句外部不可访问
    //fmt.Printf("%s", contents) // 报错
}

从上边可以看出 Go 对文件操作也非常简单。

switch:默认自带break,如果想穿下去执行,使用 fallthrough

// switch 默认自带break,如果想穿下去执行,使用 fallthrough
func eval(a, b int, op string) int  {
    var value int
    switch op {
    case "+":
        value = a + b
    case "-":
        value = a - b
    default:
        panic("unsupport operator" + op)
    }
    return value
}

五、循环

for:for 的三个组件都可省略,Go 没有 while,用 for 来替代

import (
    "fmt"
    "os"
    "bufio"
)

func sum() int {
    var value int
    for i := 0; i <= 100; i++ {
        value += i
    }
    return value
}

// 等同于 while(true)
func deadLoop() {
    for {
        fmt.Println("this is a deadLoop")
    }
}

// Go 没有while,循环全部用 for,for的三个组件都可以省略
func printFile(filename string) {
    // 打开文件
    file, err := os.Open(filename)
    // 如果出错,结束进程
    if err != nil {
        panic(err)
    }
    // 获取读取器
    scanner := bufio.NewScanner(file)
    // 读取:It returns false when the scan stops, either by reaching the end of the input or an error
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}

六、函数

func 函数

  • 可以有多个返回值
  • 函数的参数类型可以是 func - 函数式编程
  • 支持可变长参数
======================== 可以有多个返回值 =========================
// 函数可返回多个值
// 接收:q, r := div(10, 3)
// 如果只用其中一个值,另一个用下划线:q, _ := div(10, 3)
func div(a, b int) (int, int) {
    return a / b, a % b
}
// use
q, _ := div(10, 3)

======================== 函数的参数类型可以是 func =========================
// 可以使用函数作为参数,函数参数与内部参数一样,函数名在前,函数类型在后
// 后续传参,可以使用匿名内部函数,也可以先定义函数再传入
func apply(op func(int, int) int, a,b int) int {
    return op(a, b)
}
// use
result := apply(func(x int, y int) int {
    return x + y
}, 10,4)

======================== 支持可变长参数 =========================
// 可变长参数
func sum2(nums ...int) int {
    s := 0
    for i := range nums {
        s += nums[i]
    }
    return s
}
// use
sum2(1, 2, 3)

七、指针

Go 只有值传递,引用传递需要借助指针实现
引用传递实际上也是值传递,只是传递的是地址

// 值传递,函数参数拷贝了一份外界的 a, b
func swap_by_value(a, b int) {
    b, a = a, b
}
// use
a, b := 3, 4
swap_by_value(a, b)
fmt.Println(*(&a), b) // 3 4 没有实现交换

函数参数拷贝了一份外界的 a, b

// Go 只有值传递,想实现引用传递,使用指针
// *int 代表是指针类型,此时会将外界传入的 &a 拷贝给 这里的a,即这里的 a 拿到的是外界的 a 的地址
// 通过 *a,由于 a 是 &a,这里的 *a 相当于 *(&a) ,即从地址中取值
// 由于函数内部直接操作的是外界的 a,b 的内存地址,所以可以实现引用传递
func swap_by_pointer(a, b *int) {
    *b, *a = *a, *b
}
// use
swap_by_pointer(&a, &b)
fmt.Println(a, b)

*int 代表是指针类型,此时会将外界传入的 &a 拷贝给 这里的a,即这里的 a 拿到的是外界的 a 的地址
通过 *a,由于 a 是 &a,这里的 *a 相当于 *(&a) ,即从地址中取值
由于函数内部直接操作的是外界的 a,b 的内存地址,所以可以实现引用传递

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容