首页 > 编程语言 > 详细

【Go语言】笔记

时间:2020-06-06 19:33:13      阅读:43      评论:0      收藏:0      [点我收藏+]

未归档知识点

字符串末尾可以追加其他数据,但是不能修改原来的值

使用reflect包可以输出变量的类型
浮点数不指定默认是float64

package main 
import ( "fmt";"reflect" )
func main() {
    s := "aaa"
    i := 10
    f := 1.2
    fmt.Println(reflect.TypeOf(s))
    fmt.Println(reflect.TypeOf(i))
    fmt.Println(reflect.TypeOf(f))
}

数据转换 资料

string ? bool

package main 
import ( "fmt";"reflect";"strconv")
func main() {
    var s string = strconv.FormatBool(true) // 举例:将bool类型转换成string
    b,err := strconv.ParseBool(s) //举例:将string转化成bool, 会有两个返回值
    fmt.Println(reflect.TypeOf(b),b,err)
}

output:
bool true <nil>

string ? int

package main 
import ( "fmt";"strconv")
func main() {
    
    s := strconv.Itoa(32))  // int -> string
    i,_ := strconv.Atoi("3") // string -> int 成功 
    i,err := strconv.Atoi("a") // string -> int 失败
    if err != nil { //判断是否成功
        fmt.Println("converted failed", i) //i必须使用,这里的值为 0
    }
}

Parse类函数
用于转换字符串为给定类型的值:ParseBool()、ParseFloat()、ParseInt()、ParseUint()

由于字符串转换为其它类型可能会失败,所以这些函数都有两个返回值,第一个返回值保存转换后的值,第二个返回值判断是否转换成功。

b, err := strconv.ParseBool("true")
f, err := strconv.ParseFloat("3.1415", 64) //ParseFloat()只能接收float64类型的浮点数。
i, err := strconv.ParseInt("-42", 10, 64) // func ParseInt(s string, base int, bitSize int) (i int64, err error)
u, err := strconv.ParseUint("42", 10, 64) // func ParseUint(s string, base int, bitSize int) (uint64, error)

bitSize参数表示转换为什么位的int/uint,有效值为0、8、16、32、64。
当bitSize=0的时候,表示转换为int或uint类型。例如bitSize=8表示转换后的值的类型为int8或uint8。

base参数表示以什么进制的方式去解析给定的字符串,有效值为0、2-36。
当base=0的时候,表示根据string的前缀来判断以什么进制去解析:0x开头的以16进制的方式去解析,0开头的以8进制方式去解析,其它的以10进制方式解析。

// 以10进制方式解析"-42",保存为int64类型
i, _ := strconv.ParseInt("-42", 10, 64) 
// 以5进制方式解析"23",保存为int64类型
i, _ := strconv.ParseInt("23", 5, 64)
// 以16进制解析23,保存为int64类型
i, _ := strconv.ParseInt("23", 16, 64)
// 以15进制解析23,保存为int64类型
i, _ := strconv.ParseInt("23", 15, 64)

Format类函数

将给定类型格式化为string类型:FormatBool()、FormatFloat()、FormatInt()、FormatUint()

s := strconv.FormatBool(true)
s := strconv.FormatFloat(3.1415, ‘E‘, -1, 64) //func FormatFloat(f float64, fmt byte, prec, bitSize int) string
s := strconv.FormatInt(-42, 16) //func FormatInt(i int64, base int) string
s := strconv.FormatUint(42, 16) //func FormatUint(i uint64, base int) string

FormatInt的第二个参数base指定将第一个参数转换为多少进制,有效值为2<=base<=36。当指定的进制位大于10的时候,超出10的数值以a-z字母表示。

FormatFloat()的参数

  • bitSize表示f的来源类型(32:float32、64:float64),会据此进行舍入
  • fmt表示格式:‘f‘(-ddd.dddd)、‘b‘(-ddddp±ddd,指数为二进制)、‘e‘(-d.dddde±dd,十进制指数)、‘E‘(-d.ddddE±dd,十进制指数)、‘g‘(指数很大时用‘e‘格式,否则‘f‘格式)、‘G‘(指数很大时用‘E‘格式,否则‘f‘格式)
  • prec控制精度(排除指数部分):对‘f‘、‘e‘、‘E‘,它表示小数点后的数字个数;对‘g‘、‘G‘,它控制总的数字个数。如果prec 为-1,则代表使用最少数量的、但又必需的数字来表示f。

Append类函数
AppendTP类函数用于将TP转换成字符串后append到一个slice中:AppendBool()、AppendFloat()、AppendInt()、AppendUint()。

Append类的函数和Format类的函数工作方式类似,只不过是将转换后的结果追加到一个slice中

    // 声明一个slice
	b10 := []byte("int (base 10):")
    
    // 将转换为10进制的string,追加到slice中
	b10 = strconv.AppendInt(b10, -42, 10)
	fmt.Println(string(b10))

	b16 := []byte("int (base 16):")
	b16 = strconv.AppendInt(b16, -42, 16)
	fmt.Println(string(b16))

函数

函数可以有多个返回值

不定参数函数

// 实现求最大值函数
package main 
import ( "fmt" )
func max(numbers ... int) int{
    res := numbers[0]
    for _,it := range numbers {
        if res < it {
            res = it
        }
    }
    return res
}
func main() {
    
    result := max(1,3,5,2,6)
    fmt.Println(result)
}

具名返回值
指定返回值的名称,并在return前进行赋值,return时只需要裸return语句,可以增加函数的可读性

func sayHi() (x,y string) {
    x = "Hello"
    y = "world"
    return
}
func main() {
    fmt.Println(sayHi())
}
/*
output:
Hello world
*/

将函数作为值传递

package main 
import ( "fmt")

func B(f func() string) string {
    return f()
}
func main() {
    fn := func() string {
        return "ok"
    }
    fmt.Println(B(fn))
}
/*
output:
ok
*/

B接受一个签名类型为func() string的函数作为函数参数f,在B里面调用这个参数的函数f(),就执行了这个函数,返回了一个string,再把这个函数作为返回值返回到main.

它同样也可以写成下面这种形式

func B(f func() string) string {
    return f()
}
func A() string {
    return "ok"
}
func main() {
    fn := A
    fmt.Println(B(fn))
}

流程控制

Golang中没有while关键词,while循环可以用for实现

// 打印1~10
func main() {
    i:=0
    for i<10 {
        i++
        fmt.Println(i)
    }
}

类似C语言的迭代遍历,golang可以用for遍历数据结构

func main() {
    a :=[]int{1,2,3,4}
    for id,num := range a { //如果不需要序号‘id‘,可以用‘_‘代替
        fmt.Println(id,"::",num)
    }
}
/*
OUTPUT:
0 :: 1
1 :: 2
2 :: 3
3 :: 4
*/

defer语句
被defer指定的语句将在函数返回前执行,无论它被写在哪个位置

func main() {
    defer fmt.Println("this is a defer function")
    fmt.Println("hello world")
}
/*
OUTPUT:
hello world
this is a defer function
*/

如果程序里有多条defer语句,将从后往前执行

func main() {
    defer fmt.Println("defer A")
    defer fmt.Println("defer B")
    fmt.Println("hello world")
    defer fmt.Println("defer C")
}
/*
OUTPUT:
hello world
defer C
defer B
defer A
*/

一些需要使用defer语句的例子:

  • 在读取文件后将其关闭
  • 收到来自Web服务器的响应后对其进行处理以及建立连接后向数据库请求数据
  • 需要在某项工作完成后执行特定的函数

数组,切片

切片类似于数组,但可以改变长度
append函数
使用append函数可以增大切片长度,也可以删除元素,不能将delete用于切片元素

func main() {
    var d = make([]string, 2)
    d[0] = "aaa"
    d[1] = "bbb"
    d = append(d,"ccc","ddd","eee") //向d的末尾添加多个元素
    d = append(d[:2],d[3:]...) //删除d[2],将后面所有元素前移
    for id,it := range d {
        fmt.Println(id,it)
    }
}
/*
OUTPUT:
0 aaa
1 bbb
2 ddd
3 eee
*/

copy函数
copy可以在新切片中创建元素的副本,但是不能改变新切片的长度

func main() {
    a := []int {1,2,3,4} 
    a = append(a,5) //a的长度为5
    b := make([]int, 2) //b的长度为2
    copy(b,a) 
    fmt.Println(b)

}
/*
OUTPUT:
[1 2]
*/

映射

类似于c++的map

声明string → int空映射

var mp  = make(map[string]int) 

添加元素

mp["cook"] = 32

结构体

简单的例子

type Movie struct {
    Name string
    Year int
    Rating float32
}

func main() {
    m := Movie{Rating: 10, Name: "name", Year: 1999}
    fmt.Println(m)// 直接打印是按照结构体定义成员变量的顺序打印
}

/*
OUTPUT:
{name 1999 10}
*/

还可以用new方法创建实例,但是创建的是指针变量
但是在golang中指针变量访问成员变量还是用‘.‘

type Movie struct {
    Name string
    Rating float32
}

func main() {
    a := new(int)
    //var a int 
    *a = 2333
    fmt.Println(reflect.TypeOf(a))

    m := new(Movie)
    *m = Movie{
        Name:"aaa",
        Rating:9.9,
    }
    fmt.Println(reflect.TypeOf(m))
    fmt.Println(m.Name, m.Rating)
}

/*
*int
*main.Movie
aaa 9.9
*/

结构体也是可以嵌套的,当作一个普通的数据类型,类似c++

创建结构体时,如果没有给数据字段指定值,那么为golang默认的初始值

golang没有提供自定义默认值的内置方法,但可以使用自定义函数来实现这个目标

方法、接口

类似于c语言的结构体,我们可以为结构体添加成员方法,在golang要写在结构体外面,在func之后,函数名之前添加“接收者”变量,传递指针还是传递值根据是否需要改变原值来决定。

type Movie struct {
	Name   string
	Rating float64
}

func (m *Movie) summary() string {
	r := strconv.FormatFloat(m.Rating, ‘f‘, 1, 64) //将float64转化成string
	return m.Name + ", " + r
}

func main() {
	m := Movie{
		Name:   "Spiderman",
		Rating: 3.2,
	}

	fmt.Println(m.summary())
}
/*
OUTPUT:
Spiderman, 3.2
*/

接口描述了方法集中的所有方法,制定了它们的签名,但并没有实现他们。

要使用接口必须先实现它,接口定义了方法的规范,有助于代码理解

// 编写启动机器人的接口
type Robot interface {
	PowerOn() error //不接受任何参数,返回一种错误类型
}

//编写两种机器人的启动方法
type T850 struct {
	Name string
}
func (a *T850) PowerOn() error {
	return nil
}
type R2D2 struct {
	Broken bool
}
func (r *R2D2) PowerOn() error {
	if r.Broken {
		return errors.New("R2D2 is broken")
	} else {
	0	return nil
	}
}

//编写一个可用于启动任何机器人的函数, 这个函数将接口的实现作为参数
func Boot(r Robot) error {
	return r.PowerOn()
}

//各种调用方法
func main() {

	t := T850{Name: "The Terminator"}
	r := R2D2{Broken: true}
	err := Boot(&r)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println("Robot is powered on!")
	}
	err = Boot(&t)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println("Robot is powered on!")
	}
}

/*
OUTPUT:
R2D2 is broken
Robot is powered on!
*/

接口有助于代码重用,还能完全更换实现,在golang中,接口一声明的方式提供了多态

【Go语言】笔记

原文:https://www.cnblogs.com/greenty1208/p/13049328.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!