GO基础知识分享

兵长:哟,最近在干啥呢

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

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

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

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

go语言的基本事项

  1. go run hello.go 直接运行,输出结果(原理也是编译后执行)
  2. go build hello.go 生成可执行程序,运行可执行程序,输出结果
  3. 注意 go语言中花括号不能单独占一行,否则会报错
package main

import "fmt"

func main(){ //go语言中此处的花括号不能单独占一行,否则会报错
fmt.Println("hello world")
}
  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. 使用:=的方式来进行 新变量的定义,仅限于新变量 -- 适用于定义在函数内部
//字符串 可以使用+ 进行拼接
fmt.Println("this is my func")
fmt.Println("hello ,wolrd" + "xiaozhuzhu") //定义变量
var name string="xiaomotong"
var age,tail int=24,170
fmt.Println(name, age , tail)
fmt.Println(name)
fmt.Println(age)
fmt.Println(tail) //定义变量的三种方式
//1
var a int = 1
fmt.Println(a) //2 使用var定义变量,但是不定义类型,通过赋初值的方式,go编译器自动识别
var b = "hello"
fmt.Println(b) //3 使用:=的方式来进行 新变量的定义,仅限于新变量
//:= 左侧如果没有声明新的变量,就产生编译错误
c := 20
fmt.Println(c)
//c:=30 //报错,因为c已经不是新变量的
c=30 //正确,是一个正常的赋值操作
fmt.Println(c) c,d:=40,90 //这样是合法的
fmt.Println(c,d)

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

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

空白符

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

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

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

const常量

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

iota的用法

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

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

iota 可以被用作枚举值:

//itoa的用法
const(
g_a = iota
g_b
g_c
g_d
) const(
g_e = iota
g_f = "hello"
g_g
g_h = iota
g_i
) const(
g_j = 1<<iota
g_k
g_l
g_m
)
println(g_a,g_b,g_c,g_d)
println(g_e,g_f,g_g,g_h,g_i)
println(g_j,g_k,g_l,g_m)
//0 1 2 3
//0 hello hello 3 4
//1 2 4 8

运算符

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

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

算术运算符

关系运算符

逻辑运算符

位运算符

赋值运算符

其他运算符

语言条件语句

  • if xxx
if xxx {
...
}
  • if xxx {...} else{...}
if xxx{
...
}else{
...
}
  • if xxx{ ... if xxx { ...}}
if xxx{
if xxx {
...
}
...
}
  • switch
package main

import "fmt"

func main(){

	grade:= 90
if grade >= 90{
println("优秀")
}else if grade >=70 && grade <90{
println("良好")
}else{
println("差")
} var x interface{} //计算类型 switch i := x.(type){
case nil:
fmt.Printf(" x 的类型 :%T\n",i)
case int:
fmt.Printf("x 是 int 型")
default:
println("未知")
}
}
  • select

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

for循环的方式

  • 三种方式
  1. 类似C语言中的for
  2. 类似C语言中的while
  3. 死循环
package main

import "fmt"

func main(){

//类似C语言中的for
var sum int
for i:=1;i<=10;i++{
sum +=i
} fmt.Println(sum) //类似于while
for sum >30{
sum -= 10
fmt.Println(sum)
} //死循环 for {
...
}
  • For-each range 循环
//for-each  range 循环的方式
name := []string{"qqq","yyy"}
for i,str:= range name{
fmt.Printf("%d -- %s\n",i,str)
} //0 -- qqq
//1 -- yyy
------------------------------------------------------------------------
str := []string{"北京", "天津", "山东"} //可以默认丢掉第二个返回值
for i := range str {
fmt.Printf("%d -- %s\n", i, str[i])
}

函数

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

作用域

与C语言一致

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

数组&切片

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

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

切片写法如下:

name := []string{"xiaomotong","pangsir"}

nums :=[]int{1,2,3,4,5,6}

指针

var ptr1 *int

二级指针

var  a int
var ptr *int
var pptr **int ptr = &a
pptr = &ptr

指针数组

var ptr [5]*int

结构体

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

//定义一个结构体
type info struct{
name string
age int
height int
} //使用
var stu info
stu.name = "xiaomotong"
stu.age = 24
stu.height = 170 fmt.Println(stu.name,stu.age,stu.height) var stu2 *info = &stu
stu2.name = "pangsir"
stu2.age = 24
stu2.height = 160 fmt.Println(stu2.name,stu2.age,stu2.height)

切片slice

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

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

  • 使用var定义
  • 定义空slice
  • 使用:=定义
  • 使用make来定义 make([]type,len,cap)
  • apend 和 copy的使用
package main

/*
author:xiaomotong
file:slice
function:study slice for golang
*/
import "fmt" func main(){
//定义切片的方式
//1、使用var定义
var s1 = []int{1,2,3};
printInfo(s1);
//2、定义空slice
var s2 []int
printInfo(s2);
//3、使用:=定义
ss := []int{3,4,5,6}
printInfo(ss); //4、使用make来定义 make([]type,len,cap)
s3 := make([]int,2,3)
printInfo(s3);
//复制操作
s3[0] = 3
printInfo(s3);
//覆盖整个slice
s1 = s3
printInfo(s1); //apend 和 copy的使用
s3 = append(s3,6,7,8,9)
printInfo(s3);
//扩容
s4 := make([]int,len(s3),cap(s3) * 3)
copy(s4,s3)
printInfo(s4);
//s[2:]
println(s4[1:])
println(s4[:4])
println(s4[1:3])
fmt.Printf("s4[1:] = %v \n",s4[1:])
fmt.Printf("s4[:4] = %v \n",s4[:4])
fmt.Printf("s4[1:3] = %v \n",s4[1:3])
} func printInfo(s[]int){
fmt.Printf("len = %d, cap = %d, slic = %v\n",len(s),cap(s),s); }

范围Range

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

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

  • range 对于 数组、切片
  • 对于字符串
  • range对于map集合
  • 占位符_
package main

/*
author:xiaomotong
file:range
function:study range for golang
*/
import "fmt" func main(){ //1、range 对于 数组、切片 s := []string{"apple","pen"}
for i,value := range s{
fmt.Println(i,value)
} //2、对于字符串
for i,value := range "hello"{
fmt.Println(i,value)
} //3、range对于map集合
m := map[string]string{"name":"xiaopang","age":"25"}
for i,value := range m{
fmt.Println(i,value)
} //4、占位符_
sum := 0
nums := []int{1,2,3,4,5}
for _,value := range nums{
sum += value
}
fmt.Println(sum)
}

MAP集合

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

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

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

delete() 函数

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

delete(countryCapitalMap,"France")

递归函数

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

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

递归算阶乘

package main

import "fmt"

func fabulaxiaomotong(n uint 64) (result uint64){
if n>0 {
return fabulaxiaomotong(n-1)*n
}
return 1
} func main(){
fmt.Println("result : ",fabulaxiaomotong(15))
}

菲波拉契数列

func fabolaxiaomotong(n uint64)(result utin64){
if n<2{
return n
}else{
return fabolaxiaomotong(n-2)+fabolaxiaomotong(n-1)
}
}

接口

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

package main

import "fmt"

//接口
type phone interface {
call()
show()
} type xiaomi struct {
name string
ads string
} type huawei struct {
name string
ads string
} //接口实现
func (x xiaomi) call() {
fmt.Println("phoneName :", x.name)
} func (x xiaomi) show() {
fmt.Println("advertisement :", x.ads)
} func (h huawei) call() {
fmt.Println("phoneName :", h.name)
} func (h huawei) show() {
fmt.Println("advertisement :", h.ads)
} func main() {
x := xiaomi{"mi note2", "for fire"}
x.call()
x.show() h := huawei{"hw p40", "your better phone"}
h.call()
h.show()
}

错误

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

package main

import "fmt"

//定义数据结构
type DivideError struct {
devidee int
devider int
} //错误处理实现Error()接口
func (de *DivideError) Error() string {
strdata := `
error,divide is zero
dividee is %d
divider is zero
` return fmt.Sprintf(strdata, de.devidee)
} //实现功能接口
func Divide(dividee int, divider int) (result int, errMsg string) {
if divider == 0 {
data := DivideError{dividee, divider}
errMsg = data.Error()
return
} else {
return dividee / divider, ""
}
} func main() {
a := 10
b := 0
result, err := Divide(a, b)
if err != "" {
fmt.Println(err)
return
}
fmt.Printf("%d / %d == %d \n", a, b, result) }

go语言的并发

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

  • go的并发也是线程不安全的,需要加锁才安全
package main

import (
"fmt"
"time"
) func say(s string) {
var i int
for i = 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
} var num int = 0 //goroutine 是线程不安全的
func countNum() {
var i int
for i = 0; i < 10; i++ {
time.Sleep(5 * time.Millisecond)
num++
}
}
func main() {
//go say("hello")
//say("world") go countNum()
countNum()
fmt.Println(num)
}

通道(channel)

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

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

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

package main

import "fmt"

//不带缓冲的 通道
func getSum(s []int, c chan int) {
sum := 0
for _, value := range s {
sum += value
}
c <- sum
} func getSum2(c chan int, n int) {
x, y := 0, 1
var i int
for i = 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c) //关闭通道
} func main() {
//不带缓冲的 通道
// s := []int{3, 5, -2, 3, 4, 7, 1, 1, 1}
// c := make(chan int)
// go getSum(s[:3], c)
// go getSum(s[3:6], c)
// go getSum(s[6:], c)
// x, y, z := <-c, <-c, <-c
// fmt.Println(x, y, z, x+y+z) //带缓冲的通道
c := make(chan int, 10)
go getSum2(c, cap(c)) for value := range c {
fmt.Println(value)
} }

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

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

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

mylib.go

package mylib

func Add(a, b int) int {
return a + b
}

main.go

package main

import (
"fmt"
"mystudy/mylib"
) func main() {
fmt.Println(mylib.Add(2, 3))
}

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

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

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

作者:小魔童哪吒

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. HTML form All In One

    HTML form All In One action + method onsubmit, submit event action + method <form action="&q ...

  2. 如何导出android内部存储的文件(不用root)

    这段时间公司项目,涉及到数据缓存,由于需要缓冲的数据太多.太大,通过网络请求,再缓存到本地sqlite数据库,太费时间,消耗流量.所以准备先在本地保存一个标准版sqlite数据库(包含数据),打包到a ...

  3. learning free programming resources form top university of the world

    learning free programming resources form top university of the world Harvard university https://www. ...

  4. c++ x86_x64挂钩函数 传递寄存器表

    https://github.com/januwA/GameCheat #include "pch.h" #include <iostream> #include &l ...

  5. Flutte 什么是Widget,RenderObjects和Elements

    原文 Opacity API文档 有没有想过Flutter如何获取这些小部件并将其实际转换为屏幕上的像素? 您可能已经知道如何使用StatelessWidget和StatefulWidget.但是那些 ...

  6. opencv打不开摄像头

    问题描述: capFace = cv2.VideoCapture(0) 报错: VIDEOIO ERROR: V4L2: Unable to capture video memory. VIDEOIO ...

  7. 【python】递归听了N次也没印象,读完这篇你就懂了

    听到递归总觉得挺高大上的,为什么呢?因为对其陌生,那么今天就来一文记住递归到底是个啥. 不过先别急,一起来看一个问题:求10的阶乘(10!). 求x的阶乘,其实就是从1开始依次乘到x.那么10的阶乘就 ...

  8. MPAndroidChart实现LineChart(折线图)

    一.参照油管视频做法 1.引入依赖 新建Android工程,然后分别在build.gradle(Project:...)添加 maven { url 'https://jitpack.io' } 在b ...

  9. @Transaction注解失效的几种场景

    一.@Transactional介绍 1.@Transactional注解可以作用于哪些地方? @Transactional 可以作用在接口.类.类方法上. 作用于类:表示所有该类的public方法都 ...

  10. 五大自动化测试的Python框架

    1.Robot Framework 作为最重要的Python测试框架之一,Robot Framework主要被用在测试驱动(test-driven)类型的开发与验收中.虽然是由Python开发而来,但 ...