GO基础知识分享

兵长:哟,最近在干啥呢

胖sir:在看我之前的go基础学习资料呢,回顾一下

兵长:那给我分享一下呗,我也想回顾回顾

胖sir:用你的小手指点开你的手机,我来传给你

兵长:你信不信我的小手指可以带你飞整个峡谷 . . .

go语言的基本事项

  1. go run hello.go 直接运行,输出结果(原理也是编译后执行)
  2. go build hello.go 生成可执行程序,运行可执行程序,输出结果
  3. 注意 go语言中花括号不能单独占一行,否则会报错
  1. package main
  2. import "fmt"
  3. func main(){ //go语言中此处的花括号不能单独占一行,否则会报错
  4. fmt.Println("hello world")
  5. }
  1. go语言一条语句占一行,如果一行需要执行多个语句 使用 分号 隔开

  2. go语言的输出语句有3种方式

    1. import "fmt" 后适用fmt.Println(x) -- 输出
    2. println(x) -- 输出
    3. fmt.Printf("%d",x) -- 格式化输出

关键字

下面列举了 Go 代码中会使用到的 25 个关键字或保留字:

break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var

除了以上介绍的这些关键字,Go 语言还有 36 个预定义标识符:

append bool byte cap close complex complex64 complex128 uint16
copy false float32 float64 imag int int8 int16 uint32
int32 int64 iota len make new nil panic uint64
print println real recover string true uint uint8 uintptr

字符串的拼接和变量的定义方式

定义变量的三种方式

  1. 正常使用var定义变量
  2. 使用var定义变量,但是不定义类型,通过赋初值的方式,go编译器自动识别
  3. 使用:=的方式来进行 新变量的定义,仅限于新变量 -- 适用于定义在函数内部
  1. //字符串 可以使用+ 进行拼接
  2. fmt.Println("this is my func")
  3. fmt.Println("hello ,wolrd" + "xiaozhuzhu")
  4. //定义变量
  5. var name string="xiaomotong"
  6. var age,tail int=24,170
  7. fmt.Println(name, age , tail)
  8. fmt.Println(name)
  9. fmt.Println(age)
  10. fmt.Println(tail)
  11. //定义变量的三种方式
  12. //1
  13. var a int = 1
  14. fmt.Println(a)
  15. //2 使用var定义变量,但是不定义类型,通过赋初值的方式,go编译器自动识别
  16. var b = "hello"
  17. fmt.Println(b)
  18. //3 使用:=的方式来进行 新变量的定义,仅限于新变量
  19. //:= 左侧如果没有声明新的变量,就产生编译错误
  20. c := 20
  21. fmt.Println(c)
  22. //c:=30 //报错,因为c已经不是新变量的
  23. c=30 //正确,是一个正常的赋值操作
  24. fmt.Println(c)
  25. c,d:=40,90 //这样是合法的
  26. fmt.Println(c,d)

因式分解的方式,仅仅适用于定义全局变量

  1. //因式分解的方式,仅仅适用于定义全局变量
  2. var
  3. (
  4. g_a int = 1
  5. g_b,g_c int=1,2
  6. )

空白符

空白标识符 _ 也被用于抛弃值,如值 5 在:_, b = 5, 7 中被抛弃。

_ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

  1. //空白符
  2. _,e := 2,3
  3. fmt.Println(e)

const常量

  • 定义const常量
  1. //定义const常量
  2. const width,height = 10,5
  3. var area int=width*height
  4. fmt.Println("面积为", area) //50
  • const常量用作枚举
  1. const(
  2. unknow = 0
  3. man = 1
  4. woman = 2
  5. )
  6. println(unknow,man,woman) //0 1 2
  • 常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过:
  1. const(
  2. a = "hello"
  3. b = len(a)
  4. c = unsafe.Sizeof(a)
  5. )
  6. println(a,b,c) //hello 5 16

iota的用法

iota,特殊常量,可以认为是一个可以被编译器修改的常量。

iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。

iota 可以被用作枚举值:

  1. //itoa的用法
  2. const(
  3. g_a = iota
  4. g_b
  5. g_c
  6. g_d
  7. )
  8. const(
  9. g_e = iota
  10. g_f = "hello"
  11. g_g
  12. g_h = iota
  13. g_i
  14. )
  15. const(
  16. g_j = 1<<iota
  17. g_k
  18. g_l
  19. g_m
  20. )
  21. println(g_a,g_b,g_c,g_d)
  22. println(g_e,g_f,g_g,g_h,g_i)
  23. println(g_j,g_k,g_l,g_m)
  24. //0 1 2 3
  25. //0 hello hello 3 4
  26. //1 2 4 8

运算符

go语言的运算符和C语言的运算符基本一致

Go 没有三目运算符,不能适用?:

算术运算符

关系运算符

逻辑运算符

位运算符

赋值运算符

其他运算符

语言条件语句

  • if xxx
  1. if xxx {
  2. ...
  3. }
  • if xxx {...} else{...}
  1. if xxx{
  2. ...
  3. }else{
  4. ...
  5. }
  • if xxx{ ... if xxx { ...}}
  1. if xxx{
  2. if xxx {
  3. ...
  4. }
  5. ...
  6. }
  • switch
  1. package main
  2. import "fmt"
  3. func main(){
  4. grade:= 90
  5. if grade >= 90{
  6. println("优秀")
  7. }else if grade >=70 && grade <90{
  8. println("良好")
  9. }else{
  10. println("差")
  11. }
  12. var x interface{} //计算类型
  13. switch i := x.(type){
  14. case nil:
  15. fmt.Printf(" x 的类型 :%T\n",i)
  16. case int:
  17. fmt.Printf("x 是 int 型")
  18. default:
  19. println("未知")
  20. }
  21. }
  • select

    类似于C语言中的select,用于多路IO复用

for循环的方式

  • 三种方式
  1. 类似C语言中的for
  2. 类似C语言中的while
  3. 死循环
  1. package main
  2. import "fmt"
  3. func main(){
  4. //类似C语言中的for
  5. var sum int
  6. for i:=1;i<=10;i++{
  7. sum +=i
  8. }
  9. fmt.Println(sum)
  10. //类似于while
  11. for sum >30{
  12. sum -= 10
  13. fmt.Println(sum)
  14. }
  15. //死循环
  16. for {
  17. ...
  18. }
  • For-each range 循环
  1. //for-each range 循环的方式
  2. name := []string{"qqq","yyy"}
  3. for i,str:= range name{
  4. fmt.Printf("%d -- %s\n",i,str)
  5. }
  6. //0 -- qqq
  7. //1 -- yyy
  8. ------------------------------------------------------------------------
  9. str := []string{"北京", "天津", "山东"}
  10. //可以默认丢掉第二个返回值
  11. for i := range str {
  12. fmt.Printf("%d -- %s\n", i, str[i])
  13. }

函数

go语言的函数,可以有多个返回值,其余和C语言没有什么区别

作用域

与C语言一致

  • 局部变量
  • 全局变量
  • 函数形参

数组&切片

思想和C语言一致,数组是固定长度的

切片是动态扩容的,类似于C++的vector

切片写法如下:

  1. name := []string{"xiaomotong","pangsir"}
  2. nums :=[]int{1,2,3,4,5,6}

指针

  1. var ptr1 *int

二级指针

  1. var a int
  2. var ptr *int
  3. var pptr **int
  4. ptr = &a
  5. pptr = &ptr

指针数组

  1. var ptr [5]*int

结构体

go语言中的结构体变量,和结构体指针,访问结构体成员的时候,都是使用 点(.)来进行访问,如下:

  1. //定义一个结构体
  2. type info struct{
  3. name string
  4. age int
  5. height int
  6. }
  7. //使用
  8. var stu info
  9. stu.name = "xiaomotong"
  10. stu.age = 24
  11. stu.height = 170
  12. fmt.Println(stu.name,stu.age,stu.height)
  13. var stu2 *info = &stu
  14. stu2.name = "pangsir"
  15. stu2.age = 24
  16. stu2.height = 160
  17. fmt.Println(stu2.name,stu2.age,stu2.height)

切片slice

Go 语言切片是对数组的抽象。

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

  • 使用var定义
  • 定义空slice
  • 使用:=定义
  • 使用make来定义 make([]type,len,cap)
  • apend 和 copy的使用
  1. package main
  2. /*
  3. author:xiaomotong
  4. file:slice
  5. function:study slice for golang
  6. */
  7. import "fmt"
  8. func main(){
  9. //定义切片的方式
  10. //1、使用var定义
  11. var s1 = []int{1,2,3};
  12. printInfo(s1);
  13. //2、定义空slice
  14. var s2 []int
  15. printInfo(s2);
  16. //3、使用:=定义
  17. ss := []int{3,4,5,6}
  18. printInfo(ss);
  19. //4、使用make来定义 make([]type,len,cap)
  20. s3 := make([]int,2,3)
  21. printInfo(s3);
  22. //复制操作
  23. s3[0] = 3
  24. printInfo(s3);
  25. //覆盖整个slice
  26. s1 = s3
  27. printInfo(s1);
  28. //apend 和 copy的使用
  29. s3 = append(s3,6,7,8,9)
  30. printInfo(s3);
  31. //扩容
  32. s4 := make([]int,len(s3),cap(s3) * 3)
  33. copy(s4,s3)
  34. printInfo(s4);
  35. //s[2:]
  36. println(s4[1:])
  37. println(s4[:4])
  38. println(s4[1:3])
  39. fmt.Printf("s4[1:] = %v \n",s4[1:])
  40. fmt.Printf("s4[:4] = %v \n",s4[:4])
  41. fmt.Printf("s4[1:3] = %v \n",s4[1:3])
  42. }
  43. func printInfo(s[]int){
  44. fmt.Printf("len = %d, cap = %d, slic = %v\n",len(s),cap(s),s);
  45. }

范围Range

Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。

在数组和切片中它返回元素的索引和索引对应的值在集合中返回 key-value 对

  • range 对于 数组、切片
  • 对于字符串
  • range对于map集合
  • 占位符_
  1. package main
  2. /*
  3. author:xiaomotong
  4. file:range
  5. function:study range for golang
  6. */
  7. import "fmt"
  8. func main(){
  9. //1、range 对于 数组、切片
  10. s := []string{"apple","pen"}
  11. for i,value := range s{
  12. fmt.Println(i,value)
  13. }
  14. //2、对于字符串
  15. for i,value := range "hello"{
  16. fmt.Println(i,value)
  17. }
  18. //3、range对于map集合
  19. m := map[string]string{"name":"xiaopang","age":"25"}
  20. for i,value := range m{
  21. fmt.Println(i,value)
  22. }
  23. //4、占位符_
  24. sum := 0
  25. nums := []int{1,2,3,4,5}
  26. for _,value := range nums{
  27. sum += value
  28. }
  29. fmt.Println(sum)
  30. }

MAP集合

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

  1. //类似于key-value的形式
  2. map[string]string
  3. m := map[string]string{"name":"xiaozhu","age":"15"}
  4. mm := make(map[string]string)
  5. countryCapitalMap [ "France" ] = "巴黎"
  6. countryCapitalMap [ "Italy" ] = "罗马"
  7. countryCapitalMap [ "Japan" ] = "东京"
  8. countryCapitalMap [ "India " ] = "新德里"

delete() 函数

delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key

  1. delete(countryCapitalMap,"France")

递归函数

Go 语言支持递归。但我们在使用递归时,开发者需要设置退出条件,否则递归将陷入无限循环中。

递归函数对于解决数学上的问题是非常有用的,就像计算阶乘,生成斐波那契数列等。

递归算阶乘

  1. package main
  2. import "fmt"
  3. func fabulaxiaomotong(n uint 64) (result uint64){
  4. if n>0 {
  5. return fabulaxiaomotong(n-1)*n
  6. }
  7. return 1
  8. }
  9. func main(){
  10. fmt.Println("result : ",fabulaxiaomotong(15))
  11. }

菲波拉契数列

  1. func fabolaxiaomotong(n uint64)(result utin64){
  2. if n<2{
  3. return n
  4. }else{
  5. return fabolaxiaomotong(n-2)+fabolaxiaomotong(n-1)
  6. }
  7. }

接口

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口

  1. package main
  2. import "fmt"
  3. //接口
  4. type phone interface {
  5. call()
  6. show()
  7. }
  8. type xiaomi struct {
  9. name string
  10. ads string
  11. }
  12. type huawei struct {
  13. name string
  14. ads string
  15. }
  16. //接口实现
  17. func (x xiaomi) call() {
  18. fmt.Println("phoneName :", x.name)
  19. }
  20. func (x xiaomi) show() {
  21. fmt.Println("advertisement :", x.ads)
  22. }
  23. func (h huawei) call() {
  24. fmt.Println("phoneName :", h.name)
  25. }
  26. func (h huawei) show() {
  27. fmt.Println("advertisement :", h.ads)
  28. }
  29. func main() {
  30. x := xiaomi{"mi note2", "for fire"}
  31. x.call()
  32. x.show()
  33. h := huawei{"hw p40", "your better phone"}
  34. h.call()
  35. h.show()
  36. }

错误

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。error类型是一个接口类型,这是它的定义:

  1. package main
  2. import "fmt"
  3. //定义数据结构
  4. type DivideError struct {
  5. devidee int
  6. devider int
  7. }
  8. //错误处理实现Error()接口
  9. func (de *DivideError) Error() string {
  10. strdata := `
  11. error,divide is zero
  12. dividee is %d
  13. divider is zero
  14. `
  15. return fmt.Sprintf(strdata, de.devidee)
  16. }
  17. //实现功能接口
  18. func Divide(dividee int, divider int) (result int, errMsg string) {
  19. if divider == 0 {
  20. data := DivideError{dividee, divider}
  21. errMsg = data.Error()
  22. return
  23. } else {
  24. return dividee / divider, ""
  25. }
  26. }
  27. func main() {
  28. a := 10
  29. b := 0
  30. result, err := Divide(a, b)
  31. if err != "" {
  32. fmt.Println(err)
  33. return
  34. }
  35. fmt.Printf("%d / %d == %d \n", a, b, result)
  36. }

go语言的并发

Go 语言支持并发,我们只需要通过 go 关键字来开启 goroutine 即可。goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。goroutine 语法格式:

  • go的并发也是线程不安全的,需要加锁才安全
  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func say(s string) {
  7. var i int
  8. for i = 0; i < 5; i++ {
  9. time.Sleep(100 * time.Millisecond)
  10. fmt.Println(s)
  11. }
  12. }
  13. var num int = 0
  14. //goroutine 是线程不安全的
  15. func countNum() {
  16. var i int
  17. for i = 0; i < 10; i++ {
  18. time.Sleep(5 * time.Millisecond)
  19. num++
  20. }
  21. }
  22. func main() {
  23. //go say("hello")
  24. //say("world")
  25. go countNum()
  26. countNum()
  27. fmt.Println(num)
  28. }

通道(channel)

  • 通道(channel)是用来传递数据的一个数据结构。通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。

    • 注意:默认情况下,通道是不带缓冲区的。发送端发送数据,同时必须有接收端相应的接收数据。以下实例通过两个 goroutine 来计算数字之和,在 goroutine 完成计算后,它会计算两个结果的和:
  • 通道可以设置缓冲区,通过 make 的第二个参数指定缓冲区大小

  • Go 通过 range 关键字来实现遍历读取到的数据,类似于与数组或切片

  1. package main
  2. import "fmt"
  3. //不带缓冲的 通道
  4. func getSum(s []int, c chan int) {
  5. sum := 0
  6. for _, value := range s {
  7. sum += value
  8. }
  9. c <- sum
  10. }
  11. func getSum2(c chan int, n int) {
  12. x, y := 0, 1
  13. var i int
  14. for i = 0; i < n; i++ {
  15. c <- x
  16. x, y = y, x+y
  17. }
  18. close(c) //关闭通道
  19. }
  20. func main() {
  21. //不带缓冲的 通道
  22. // s := []int{3, 5, -2, 3, 4, 7, 1, 1, 1}
  23. // c := make(chan int)
  24. // go getSum(s[:3], c)
  25. // go getSum(s[3:6], c)
  26. // go getSum(s[6:], c)
  27. // x, y, z := <-c, <-c, <-c
  28. // fmt.Println(x, y, z, x+y+z)
  29. //带缓冲的通道
  30. c := make(chan int, 10)
  31. go getSum2(c, cap(c))
  32. for value := range c {
  33. fmt.Println(value)
  34. }
  35. }

自己调用别的包/自己的包

自己调用别人的包或者自己的包,如上目录结构

  • 自己写的包名,要和目录名一样
  • 使用go mod 模块 ,执行 go mod init mystudy

mylib.go

  1. package mylib
  2. func Add(a, b int) int {
  3. return a + b
  4. }

main.go

  1. package main
  2. import (
  3. "fmt"
  4. "mystudy/mylib"
  5. )
  6. func main() {
  7. fmt.Println(mylib.Add(2, 3))
  8. }

以上为本期全部内容,如有疑问可以在评论区或后台提出你的疑问,我们一起交流,一起成长。

好家伙要是文章对你还有点作用的话,请帮忙点个关注,分享到你的朋友圈,分享技术,分享快乐

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

作者:小魔童哪吒

GO基础知识分享的更多相关文章

  1. XML的相关基础知识分享(二)

    前面我们讲了一下XML相关的基础知识(一),下面我们在加深一下,看一下XML高级方面. 一.命名空间 1.命名冲突 XML命名空间提供避免元素冲突的方法. 命名冲突:在XML中,元素名称是由开发者定义 ...

  2. docker 基础知识分享ppt

    给团队做的docker基础分享ppt, 见下面的附件. https://files.cnblogs.com/files/harrychinese/docker_intro.pptx

  3. Elasticsearch基础知识分享

    1. Elasticsearch背景介绍 Elasticsearch 是一个基于 Lucene 的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful web 接口.Elast ...

  4. XML的相关基础知识分享

    XML和Json是两种最常用的在网络中数据传输的数据序列化格式,随着时代的变迁,XML序列化用于网络传输也逐渐被Json取代,前几天,单位系统集成开发对接接口时,发现大部分都用的WebService技 ...

  5. 工作随笔—Java容器基础知识分享(持有对象)

    1. 概述 通常,程序总是运行时才知道的根据某些条件去创建新对象.在此之前,不会知道所需对象的数量,甚至不知道确切的类型,为解决这个普遍的编程问题:需要在任意时刻和任意位置创建任意数量的对象,所以,就 ...

  6. asch相关的linux基础知识分享

    本文针对的人群:会用putty.SecureCRT.xhsell等工具ssh连接到自己的asch服务器上,但不怎么会执行命令的人.高手请绕路~ 本文主要围绕受托人搭建.维护涉及相关的内容进行Linux ...

  7. PostgreSQL基础知识分享

    1.架构 PostgreSQL是一个关系数据库,采用c/s架构.一个PostgreSQL会话包括: 服务端进程——postgres:用于管理数据库文件,并接受来自客户端的数据库连接, 同时代替客户端执 ...

  8. Unity3D基础知识梳理

    这段时间在做Unity的项目,这差不多是我的第一次实战啊~然后公司来了实习的童鞋要学Unity,但是我一向不靠谱啊,所以只能帮他们稍微梳理下基础的东西了啊,唉~学长只能帮你们到这里了~顺便就把自己这两 ...

  9. Objective-c基础知识学习笔记

    Objective-c基础知识学习笔记(一) 一直有记录笔记的习惯.但非常久没分享一些东西了,正好上半年開始学习IOS了,如今有空写点.因开发须要,公司特意为我们配置了几台新MAC.还让我们自学了2周 ...

随机推荐

  1. JSON-LD & SEO

    JSON-LD & SEO https://json-ld.org/ https://en.wikipedia.org/wiki/JSON-LD Google Search structure ...

  2. css break-inside

    css break-inside The break-inside CSS property sets how page, column, or region breaks should behave ...

  3. Beacon API

    Beacon API User Tracking https://caniuse.com/#feat=beacon Question & Solution Beacon API 不会延缓网页卸 ...

  4. React + GraphQL 2020 速成课程

    React + GraphQL 2020 速成课程 technologies React (to build our user interface) GraphQL (to get and chang ...

  5. TypeScript Generics

    TypeScript Generics https://www.typescriptlang.org/docs/handbook/generics.html 泛型 1 Generic Interfac ...

  6. java数据类型(基础篇)

    public class note02 { public static void main(String[] args) { //八大基本数据类型 //1.整数 byte num1 = 1; shor ...

  7. HTTP 1.x 学习笔记 —— Web 性能权威指南

    HTTP 1.0的优化策略非常简单,就一句话:升级到HTTP 1.1.完了! 改进HTTP的性能是HTTP 1.1工作组的一个重要目标,后来这个版本也引入了大量增强性能的重要特性,其中一些大家比较熟知 ...

  8. docker镜像常用操作的基本命令

    1.拉取/下载镜像 docker pull 镜像名称       (可以从网易云镜像中心获取要下载的镜像) 2.查看已经下载的镜像 docker images 3.删除本地镜像 docker rmi ...

  9. Python数据读取函数

    1.读取mat数据 import scipy.io as sio data_mat = sio.loadmat(data.mat) 官方文档 获取的数据为字典型,其中"data"为 ...

  10. TextView 的append后面 马上调用fullScroll(),会发现无法滚动到真正的底部

    如果在TextView的append后面马上调用fullScroll,会发现无法滚动到真正的底部,这是因为Android下很多(如果不是全部的话)函数都是基于消息的,用消息队列来保证同步,所以函数调用 ...