Golang 知识点

栏目: Go · 发布时间: 7年前

内容简介:任何空值(nil)或者零值(0, 0.0, "")都不能作为布尔型来直接判断。go build: 编译出可执行文件go install: go build + 把编译后的可执行文件放到GOPATH/bin目录下

变量声明

var a
a=100
//或
var b = 100
//或
var c int = 100

// := 是声明并赋值,并且系统自动推断类型,不需要var关键字
d := 100
package main

import "fmt"

// 指针
func main() {
    // 切片的一种定义方式是 用 make
    // var x = make([]float64, 5) ,切片用make
    //另外一种是通过数组切片赋值,采用[low_index:high_index]的方式获取数值切片,其中切片元素包括low_index的元素,但是不包括high_index的元素。

    ar := new([3]int)// 指针
    ar1 := [3]int{0, 0, 0}
    var ar2 = [3]int{0, 0, 0}
    var ar3 [3]int
    var ar4 = [3]int{0: 1, 1: 2, 2: 3}
    fp(ar)
    fp(&ar1)
    fp(&ar2)
    fp(&ar3)
    fp(&ar4)

    fp1(ar)
    fp1(&ar1)
    fp1(&ar2)
    fp1(&ar3)
    fp1(&ar4)

}

func fp(a *[3]int)  { print(*a) }
func fp1(a *[3]int) { print(a) }

Python 不同

任何空值(nil)或者零值(0, 0.0, "")都不能作为布尔型来直接判断。

func main() {
    if 0 {
        fmt.Println("hello world")
    }
    if nil {
        fmt.Println("hello world")
    }
    if "" {
        fmt.Println("hello world")
    }
}

常用命令

go build: 编译出可执行文件

go install: go build + 把编译后的可执行文件放到GOPATH/bin目录下

go get: git clone + go install

何时使用指针

指针的一大用途就是可以将变量的指针作为实参传递给函数,从而在函数内部能够直接修改实参所指向的变量值。

Go的变量传递都是值传递。

package main

import (
    "fmt"
)

func change(x int) {
    x = 200
}
func main() {
    var x int = 100
    fmt.Println(x)
    change(x)
    fmt.Println(x)
}
上面的例子输出结果为

100
100
很显然,change函数改变的仅仅是内部变量x的值,而不会改变传递进去的实参。其实,也就是说 Go 的函数一般关心的是输出结果,而输入参数就相当于信使跑到函数门口大叫,你们这个参数是什么值,那个是什么值,然后就跑了。你函数根本就不能修改它的值。不过如果是传递的实参是指针变量,那么函数一看,小子这次你地址我都知道了,哪里跑。那么就是下面的例子:

package main

import (
    "fmt"
)

func change(x *int) {
    *x = 200
}
func main() {
    var x int = 100
    fmt.Println(x)
    change(&x)
    fmt.Println(x)
}
上面的例子中,change函数的虚参为整型指针变量,所以在main中调用的时候传递的是x的地址。然后在change里面使用*x=200修改了这个x的地址的值。所以x的值就变了。这个输出是:

100
200

一个函数何时该用指针类型做receiver对初学者而言一直是个头疼的问题。如果不知道该如何取舍,选择指针类型的receiver。但有些时候value receiver更加合适,比如对象是一些轻量级的不变的structs,使用value receiver会更加高效。下面是列举了一些常用的判断指导。

如果receiver是map、func或者chan,不要使用指针

如果receiver是slice并且该函数并不会修改此slice,不要使用指针

如果该函数会修改receiver,此时一定要用指针

如果receiver是struct并且包含互斥类型sync.Mutex,或者是类似的同步变量,receiver必须是指针,这样可以避免对象拷贝

如果receiver是较大的struct或者array,使用指针则更加高效。多大才算大?假设struct内所有成员都要作为函数变量传进去,如果觉得这时数据太多,就是struct太大

如果receiver是struct,array或者slice,并且其中某个element指向了某个可变量,则这个时候receiver选指针会使代码的意图更加明显

如果receiver使较小的struct或者array,并且其变量都是些不变量、常量,例如time.Time,value receiver更加适合,因为value receiver可以减少需要回收的垃圾量。

最后,如果不确定用哪个,使用指针类的receiver

常量

变量定义的类型推断方式 := 不能够用来定义常量

快速声明

Go还提供了一种同时定义多个变量或者常量的快捷方式。

import (
"fmt"
)

func main() {
    var (
        a int     = 10
        b float64 = 32.45
        c bool    = true
    )
    const (
        Pi   float64 = 3.14
        True bool    = true
    )

    fmt.Println(a, b, c)
    fmt.Println(Pi, True)
}

if 判断的()

package main

import (

"fmt"

)

func main() {

const Male = 'M'

const Female = 'F'

var dog_age = 10
var dog_sex = 'M'

if (dog_age == 10 && dog_sex == 'M') {
    fmt.Println("dog")
}

}

但是如果你使用Go提供的格式化 工具 来格式化这段代码的话,Go会智能判断你的括号是否必须有,否则的话,会帮你去掉的。你可以试试。

go fmt test_bracket.go
然后你会发现,咦?!果真被去掉了。

#  for 循环

package main

import (

"fmt"

)

在Go里面没有提供while关键字,如果你怀念while的写法也可以这样:

func main() {
    var i int = 1

    for i <= 100 {
        fmt.Println(i)
        i++
    }
}
或许你会问,如果我要死循环呢?是不是for true?呵呵,不用了,直接这样。

for{

}

切片

我们发现arr1的长度变为11,因为元素个数现在为11个。另外我们发现arr1的容量也变了,变为原来的两倍。

这是因为Go在默认的情况下,如果追加的元素超过了容量大小,Go会自动地重新为切片分配容量,容量大小为原来的两倍。

总结一下,数组和切片的区别就在于[]里面是否有数字或者...!!!!!!!!!!!

因为数值长度是固定的,而切片是可变的。

函数预定义

命名返回值

Go的函数很有趣,你甚至可以为返回值预先定义一个名称,在函数结束的时候,直接一个return就可以返回所有的预定义返回值。例如上面的例子,我们将sum作为命名返回值。

package main

import (
"fmt"
)

func slice_sum(arr []int) (sum int) {
    sum = 0
    for _, elem := range arr {
        sum += elem
    }
    return
}

func main() {
    var arr1 = []int{1, 3, 2, 3, 2}
    var arr2 = []int{3, 2, 3, 1, 6, 4, 8, 9}
    fmt.Println(slice_sum(arr1))
    fmt.Println(slice_sum(arr2))
}

这里要注意的是,如果你定义了命名返回值,那么在函数内部你将不能再重复定义一个同样名称的变量。比如第一个例子中我们用sum := 0来定义和初始化变量sum,而在第二个例子中,我们只能用sum = 0初始化这个变量了。因为 := 表示的是定义并且初始化变量。

异常处理

panic & recover

当你周末走在林荫道上,听着小歌,哼着小曲,很是惬意。突然之间,从天而降瓢泼大雨,你顿时慌张(panic)起来,

没有带伞啊,淋着雨感冒就不好了。于是你四下张望,忽然发现自己离地铁站很近,那里有很多卖伞的,心中顿时又安定了下来(recover),于是你飞奔过去买了一把伞(defer )

Go语言提供了关键字defer来在函数运行结束的时候运行一段代码或调用一个清理函数。上面的例子中,虽然second()函数写在first()函数前面,但是由于使用了defer标注,所以它是在main函数执行结束的时候才调用的。

package main

import (
    "fmt"
)

func main() {

    //defer一定是在函数执行结束的时候运行的。不管是正常结束还是异常终止,相当于finally
    defer func() {
        //panic用来触发异常,而recover用来终止异常并且返回传递给panic的值。(注意recover并不能处理异常,而且recover只能在defer里面使用,否则无效。)
        msg := recover()
        fmt.Println(msg)
    }()
    fmt.Println("I am walking and singing...")
    panic("It starts to rain cats and dogs")
}

指针

定义

所谓指针其实你可以把它想像成一个箭头,这个箭头指向(存储)一个变量的地址。

因为这个箭头本身也需要变量来存储,所以也叫做指针变量。

new 的使用发现

package main

import (
    "fmt"
)

func set_value(x_ptr *int) {

//指针指向的地址内容设置为100
    *x_ptr = 100
}
func main() {
    //开辟一块内存,用于存贮指针地址,且此指针地址的变量名为x_ptr
    x_ptr := new(int)

    set_value(x_ptr)

    //指针变量指向的地址,因为本身就是指针变量,存贮的就是指向的地址
    fmt.Println(x_ptr)
    //指针变量本身的地址
    fmt.Println(&x_ptr)

    //打印指针变量指向的地址内容
    fmt.Println(*x_ptr)
}

0xc084000040
0xc084000038
100

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Cascading Style Sheets 2.0 Programmer's Reference

Cascading Style Sheets 2.0 Programmer's Reference

Eric A. Meyer / McGraw-Hill Osborne Media / 2001-03-20 / USD 19.99

The most authoritative quick reference available for CSS programmers. This handy resource gives you programming essentials at your fingertips, including all the new tags and features in CSS 2.0. You'l......一起来看看 《Cascading Style Sheets 2.0 Programmer's Reference》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具