理解以下知识,初步写简单go项目就足够了

语言参考(基础篇)

基本语法

基本组成

  • 包声明
  • 引入包
  • 函数
  • 变量
  • 语句 & 表达式
  • 注释
  • 其它(可忽略)
    • go没有像php、js那样需要在文件开始申明 <?php ... 或者 <script>
    • 注释:多行 /* * 单行 //
    • 字符串链接符+
    • 标记:可以是关键字,标识符,常量,字符串,符号。
      • 标识符:标识符用来命名变量、类型等程序实体 ;一个标识符实际上就是一个或是多个字母(AZ和az)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。

数据类型

  • 布尔值:truefalse
  • 数字类型
  • 字符串类型
  • 派生类型:依据上面是三个基础类型,衍生出的新类型
    • 指针类型(Pointer)
    • 数组类型(数组)
    • 结构化体类型(结构体)
    • Channel类型
    • 函数类型
    • 切片类型
    • 接口类型
    • Map类型
布尔类型

布尔类型就只有真假,truefalse

数据类型

会根据系统架构(如32位、64位系统)变化的类型

  • int
  • uint
  • uintptr

明确范围的数字类型

  • 整型

    • 无符号型

      • uint8 范围(0 ~255) 2百
      • uint16 范围(0 ~ 65535) 6万
      • uint32 范围(0 ~ 4294967295) 42亿
      • uint64 范围(0 ~ 18446744073709551615)184京
    • 有符号型(范围最大值小减半)
      • int8
      • int16
      • int32
      • int64
  • 浮点型
  • 其它数字类型
    • byte =》 uint8
    • rune =》 int32
    • uint
    • int
    • uintptr 无符号型

变量

定义

var identifier type
var identifier1, identifier2 type

说明

变量生命关键字 var

变量名称:identifier

变量类型:type

常用的几种声明方式

第一种:标准定义

指定变量类型,如果没有初始化,则变量默认为零值。

//var identifier type
var a int
//a值为0
  • 数值类型(包括complex64/128)为 0
  • 布尔类型为 false
  • 字符串为 ""(空字符串)
  • 以下几种类型为 nil
第二种:自适应

根据值自行判定变量类型。

//var identifier = value
var a = 100
//a值为100 类型 int
第三种: :=

不使用 var 声明,用 := 声明变量

//value_name := value
a := 100
//等同于
// var a int
// a = 100
//注意:所以这里的a如果被声明过,这里再次var声明就会报错

派生类型声明定义方式不同,后面会讲到

多个变量声明

//法一
var a,b,c int
//-----环境分割线---------------------
//法二
var a,b,c = 100,200,300
//-----环境分割线---------------------
//法三
a,b,c := 100,200,300
//法四
//下面这种因式分解关键字的写法一般用于声明全局变量
var (
vname1 v_type1
vname2 v_type2
)

常量

定义

const identifier [type] = value
//如果不定义类型,会根据值自动确定类型

特殊常量 iota ,每次出现自增,但是每次CONST关键字出现时,将会被重置为0

表达式

变量使用

作用域

Go 语言中变量可以在三个地方声明:

  • 函数内定义的变量称为局部变量
  • 函数外定义的变量称为全局变量
  • 函数定义中的变量称为形式参数

定义

字符串、数字、布尔
//字符串
var a = "abc"
//数字
var b = 1
//布尔
var c = true

总结:字面量的类型定义使用常规定义就行var identifier = value ,变种不过多阐述。

//注意:  字符串使用双引号;单引号一般使用单个字符,并且还不是字符串类型,而是数据类型(type untyped rune,值为ASCII 码对应值)。
数组

数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型

//声明: var variable_name [SIZE] variable_type
var calss_member [60] string
//赋值: variable_name[0] = "Tom" //初始化
var class_member_1 =[5]string{"Jim","Tom","Neo","Lucy","Mei"}
class_member_2 :=[5]string{"Jim","Tom","Neo","Lucy","Mei"}
//不确定长度
class_member_3 =[...]string{"Jim","Tom","Neo","Lucy","Mei"}

总结:

  • {}中元素的个数,不能大于[]中指定的长度
  • 不知道长度时,可以使用...代替
  • 访问数据使用下标索引,从0开始
//多维数组
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type //初始化 例子
a := [3][4]int{
{0, 1, 2, 3} , /* 第一行索引为 0 */
{4, 5, 6, 7} , /* 第二行索引为 1 */
{8, 9, 10, 11}, /* 第三行索引为 2 */
}
//那么[2][2][2][2][2]是什么样子呢?
a := [2][2][2][2][2] int {
{
{
{
{1,2},
{3,4},
},
{
{5,6},
{7,8},
},
},
{
{
{9,10},
{11,12},
},
{
{13,14},
{15,16},
},
},
},
{
{
{
{17,18},
{19,20},
},
{
{21,22},
{23,24},
},
},
{
{
{25,26},
{27,28},
},
{
{29,30},
{31,32},
},
},
},
}
指针

一个指针变量指向了一个值的内存地址。

所以指针变量储存的是地址,同时操作的也是地址(上的值),因为地址无法修改。当一个指针被定义后没有分配到任何变量时,它的值为 nil。

//举例:jack的钱包里有100元
var jack int
var point_jack *int
jack = 100
point_jack = &jack //拿到钱包
*point_jack = 50 //操作钱包中的钱,放50元
fmt.Println(jack) //jack只有五十了
// 50

使用

//定义
// var var_name *var-type
var point_jack *int
// & 取地址
var num = 100
point_jack = &num
// * 使用
fmt.Println(*point_jack)
// 操作(不能掉了符号*)
*point_jack = 50
结构体

结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

/* 定义  */
type struct_variable_type struct {
member definition
member definition
...
member definition
}
// 例子,如一个学生有ID、名字、学号、自我介绍
type student struct {
id int
name string
code string
dis string
} /* 变量声明 */
variable_name := structure_variable_type {value1, value2...valuen}

variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
//例子
Jack := student{1,"Jack","10001","一个叫jack的孩子"}
Neo := student{id:2,naem:"Neo",code:"10002",dis:"一个叫Neo的孩子"} /* 使用 */
variable_name.key
//例子
Jack.dis

结构体在函数中的使用

func main()  {
Jack := student{1,"Jack","10001","一个叫jack的孩子"}
fmt.Println(Jack.dis)
var jk *student
var num *int
code := 1231231;
num = &code
jk = &Jack
show(jk,num)
} func show(stu *student,id *int) {
fmt.Println(stu.dis)
fmt.Println(*id)
} /* 函数运行结果 */
//一个叫jack的孩子
//一个叫jack的孩子
//1231231

总结:

  • 结构体是一个指定的数据结构,访问时使用符号.访问
  • 指针结构体访问和普通结构体访问没区别,但是基本类型指针访问值需要加前缀符号*
切片(slice)

Go 语言切片是对数组的抽象。数组的长度是固定的,切片的长度是不固定的。一个切片在未初始化之前默认为 nil,长度为 0

/* 定义  */
var identifier []type
// 其它定义方式
var slice1 []type = make([]type, len)
slice1 := make([]type, len)
make([]T, length, capacity) // 初始化(变量声明)
variable_name := [] variable_type {value1, value2...valuen}
variable_name := 数组[start_index:end_index]
//例子
name := []string{"Tom","Jim","Neo"}
arr := [5]int{1,2,3,4,5}
slice_arr :=arr[2:4] /* 使用 */
variable_name[index]
//例子
fmt.Println(name);
fmt.Println(slice_arr);
fmt.Println(slice_arr[0]); -------
[Tom Jim Neo]
[3 4]
3

从上面可以看到切片常用的操作

/*
截取 [start_index:end_index] 明显索引范围是半包围,即 start_index 到 end_index -1 // 常见的截取如下:
[start_index:end_index]
[start_index:]
[:end_index] // len() 和 cap() 函数
var numbers = make([]int,3,5)
len(numbers) => 3
cap(numbers) => 5
fmt.Println(numbers) => [0,0,0] //空(nil)切片 //nil 空值,未赋值前变量的值
var numbers []int
if(numbers == nil){
fmt.Printf("切片是空的")
}
*/ //append() 和 copy() 函数
slice_int1 := [] int //空切片, []
slice_int1 = append(slice_int1,1) //[1]
slice_int2 = []int{10,11,12}
copy(slice_int1,slice_int2) // slice_int1 => [1,10,11,12]
范围(rang)

Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。

//有点类似 PHP语言的 as ,使用方法如下
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
fmt.Println(num)
}
集合(map)

Map 是一种无序的键值对的集合。

/* 定义 */
// 声明变量;默认 map 是 nil 和切片,指针一样
var variable map[key_type]value_type // make 函数
variable := make(map[key_type]value_type) /* 初始化(变量声明) */
var name_CN map[string]string
name_CN['Jim'] = "张三"
name_CN['Lilei'] = "李雷"
name_CN['Hanmeimei'] = "韩梅梅" num_EN := map[string]string{"one":1,"two":2} /* 删除元素: delete() 函数 */
delete(map,index) delete(name_CN,"Jim")

类型转换

类型转换用于将一种数据类型的变量转换为另外一种类型的变量。

type_name(expression)

/* 例如 */

var money = 199.99
var pay int pay = int(money)
fmt.Println(pay)
//199

运算符

  • 算术运算符:(假定有变量 a 和 b ,a=100, b=200)

    • + a+b
    • - a-b
    • * a*b
    • / a/b
    • % a%b
    • ++ a++
    • -- a--
  • 关系运算符

    • ==
    • !=
    • >
    • <
    • >=
    • <=
  • 逻辑运算符

    • &&
    • ||
    • !
  • 位运算符

    • &
    • |
    • ^
    • <<
    • >>
  • 赋值运算符

    • =
    • 前缀= a+=b ;a*=b 等
  • 其他运算符

    • & 取地址
    • * 地址指向值

流程控制

if

if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
} // 例如,a=100 if a > 50 {
fmt.Printf("> 50")
}

if...else

if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
} else {
/* 在布尔表达式为 false 时执行 */
} // 例如,a=100 if a > 50 {
fmt.Printf("> 50")
}else{
fmt.Printf("< 50")
}

if 嵌套

if 布尔表达式 1 {
/* 在布尔表达式 1 为 true 时执行 */
if 布尔表达式 2 {
/* 在布尔表达式 2 为 true 时执行 */
}
} // 例如,a=100
if a > 50 {
fmt.Printf("> 50")
if a > 80{
fmt.Printf("> 80")
}
}

switch

switch var1 {
case val1:
...
case val2:
...
default:
...
}
// 例如,成绩有 S,A,B,C,D zhangsan ='B'
switch zhangsan {
case 'S':
fmt.Printf("优")
case 'A':
fmt.Printf("良")
case 'B':
fmt.Printf("一般")
case 'C','D':
fmt.Printf("不及格")
default:
fmt.Printf("没有成绩")
} //fallthrough 强制执行,继续执行后面的选项,并且下一个还是强制执行
package main import "fmt" func main() { var a = 'B' switch a {
case 'S':
fmt.Println("S")
fallthrough
case 'A':
fmt.Println("A")
case 'B':
fmt.Println("B")
fallthrough
case 'C':
fmt.Println("C")
case 'D':
fmt.Println("D")
fallthrough
default:
fmt.Println("other")
}
}
//
B
C

select

后期体会

for循环

//for
for init; condition; post { } for condition { } for { } //搭配使用 break continue goto //例子:
package main import "fmt" func main() { var i int
for i = 0; i<10;i++ {
fmt.Println(i)
}
for ; i<20;{
i++
fmt.Println(i)
}
for i<30 {
i++
if(i%2 == 0){
continue
}
fmt.Println(i)
} for {
i++
fmt.Println(i)
if i>40 {
break
}
}
goto LOOP
fmt.Println("你可能出不来")
LOOP:fmt.Println("果然出不来")
}

函数

函数是基本的代码功能块,用来实现一个基本功能。

/* 定义 */
func function_name(param type [,param type,param type])[return_type]{ }
/* 例子 */
func double(x int)int {
return x*2
}
func changePosition(x,y int)(int,int) {
return y,x
}

接口

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

/* 定义 */
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
} type struct_name struct { }
/* 实现 */
func (struct_varibale_name struct_name) method_name()[return_type]{ } /* 示例 */

异常处理

内置的go错误处理接口

type error interface {
Error() string
}

举例

package main

import "fmt"
import "errors" func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("math: error")
}
return f*f , errors.New("math: ok")
} func main(){
result, err:= Sqrt(22)
if err != nil {
fmt.Println(err)
}
fmt.Println(result)
} //math: ok
//484

并发

Go 语言支持并发,我们只需要通过 go 关键字来开启 goroutine 即可。

goroutine

goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。

goroutine 语法格式:

/* 定义 */
go 函数名( 参数列表 ) /* 例子 */
package main
import "fmt"
import "time" func message(message string){
for i := 0; i < 5; i++ {
time.Sleep(1 * time.Second)
fmt.Println(message)
}
}
func main() {
message("000")
go message("111")
message("222")
} // 输出
000
000
000
000
000
111
222
222
111
111
222
111
222
222
111
//结论:1.主流程不受影响,还是顺序执行;2.新启动的流程和主流程同时在执行
channel

通道(channel)是用来传递数据的一个数据结构。

通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。

操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。

package main
import "fmt"
import "time" func tmpCache(a int,b int ,cache chan int){
num := 0 fmt.Println("node 2:")
fmt.Println(time.Now()) time.Sleep(3 * time.Second) num = (a+b)*(a-b)/2
cache <- num
}
func main() {
message :=make(chan int)
count := 0 fmt.Println("node 1:")
fmt.Println(time.Now()) go tmpCache(1,100,message) fmt.Println("node 3:")
fmt.Println(time.Now()) // time.Sleep(1 * time.Second) count = <- message
fmt.Println("node 4:")
fmt.Println(time.Now()) fmt.Println(count) }
//结果
node 1:
2021-09-15 16:48:35.746247 +0800 CST m=+0.000101265
node 3:
2021-09-15 16:48:35.746418 +0800 CST m=+0.000271887
node 2:
2021-09-15 16:48:35.746425 +0800 CST m=+0.000278833
node 4:
2021-09-15 16:48:38.748364 +0800 CST m=+3.002355026
-4999
// 注意点:node 2 到 node 4 有3秒;说明阻塞了3秒
package main
import "fmt" func tmpCache(a int,b int ,cache chan int){
num := 0
// time.Sleep(3 * time.Second)
num = (a+b)*(a-b)/2
cache <- num
close(cache)
}
func main() {
message :=make(chan int) go tmpCache(0,5,message)
go tmpCache(5,10,message)
go tmpCache(10,15,message)
go tmpCache(15,20,message)
go tmpCache(20,25,message)
//close(message)
fmt.Println("===================")
for i := range message{
fmt.Println(i)
}
} //结果1
===================
-12
-62
-37
-87
-112
//结果2
===================
-12
panic: send on closed channel goroutine 22 [running]:
main.tmpCache(0x0, 0x0, 0x0)
/Users/liupeng/go/test/src/heelo/func_channel1.go:8 +0x45
created by main.main
/Users/liupeng/go/test/src/heelo/func_channel1.go:19 +0x1cf
exit status 2
//结果3
===================
-12
-37
-62

总结:

  • 通道消息是按队列进出的
  • rang使用到通道时,会有异常关闭情况,如结果3明显是没有跑完,进程就关闭了;所以开启的进程数是1时可以(在异步函数中)关闭进程

Go学习【01】:初步学习需要的知识的更多相关文章

  1. json2.js的初步学习与了解

    json2.js的初步学习与了解,想要学习json的朋友可以参考下. json2.js的初步学习与了解 1.)该js的下载地址是:http://www.json.org/json2.js 2.)在页面 ...

  2. JVM学习01:内存结构

    JVM学习01:内存结构 写在前面:本系列分享主要参考资料是  周志明老师的<深入理解Java虚拟机>第二版. 内存结构知识要点Xmind梳理 案例分析 分析1 package com.h ...

  3. Git的初步学习

    前言 感谢! 承蒙关照~ Git的初步学习 为什么要用Git和Github呢?它们的出现是为了用于提交项目和存储项目的,是一种很方便的项目管理软件和网址地址. 接下来看看,一家公司的基本流程图: 集中 ...

  4. 语法分析器初步学习——LISP语法分析

    语法分析器初步学习——LISP语法分析 本文参考自vczh的<如何手写语法分析器>. LISP的表达式是按照前缀的形式写的,比如(1+2)*(3+4)在LISP中会写成(*(+ 1 2)( ...

  5. VirtualBox上LInux命令初步学习

    大二的寒假已经接近了尾声,寒假期间我初步使用了VirtualBox虚拟机软件,并安装了ubuntu的操作系统进行了Linux语言的学习.然而寒假期间的学习没有太多的计划,纯粹是为了完成作业而应付性的学 ...

  6. 20145219 《Java程序设计》第01周学习总结

    20145219 <Java程序设计>第01周学习总结 教材学习内容总结 软件分类:系统软件(DOS.Windows.Linux等).应用软件(扫雷.QQ等) 人机交互方式:图形化界面.命 ...

  7. 以太坊web3开发初步学习

    以太坊web3开发初步学习 此文是对https://learnblockchain.cn/2018/04/15/web3-html/的学习再理解. 以太坊智能合约通过使用web3.js前端和智能合约交 ...

  8. Python学习--01入门

    Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...

  9. 学习 shell脚本之前的基础知识

    转载自:http://www.92csz.com/study/linux/12.htm  学习 shell脚本之前的基础知识 日常的linux系统管理工作中必不可少的就是shell脚本,如果不会写sh ...

  10. Java虚拟机JVM学习01 流程概述

    Java虚拟机JVM学习01 流程概述 Java虚拟机与程序的生命周期 一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这 ...

随机推荐

  1. Longhorn 企业级云原生容器存储解决方案-部署篇

    内容来源于官方 Longhorn 1.1.2 英文技术手册. 系列 Longhorn 是什么? Longhorn 云原生分布式块存储解决方案设计架构和概念 安装 Longhorn 可以通过多种方式安装 ...

  2. 让div占据父元素剩下的所有位置

    场景模拟: 现在有一个父容器,里面有俩个div,左边的要给一个固定的200px的宽度,父容器剩下的宽度都归右边的div该怎么完成?HTML代码: <div class="wrap&qu ...

  3. WPF 显示3D密集场景,堆场管理系统

    又好久好久没写博客了,这次接着上文https://www.cnblogs.com/CSSZBB/p/12785380.html,上文用WPF 的绘图功能,制作了一个伪3D的2.5D控件ThreeDBo ...

  4. beeline: 新版连接Hive server的工具

    HiveServer2 支持一个新的命令行Shell,称为Beeline,它是基于SQLLine CLI的JDBC客户端.它是从 Hive 0.11版本引入的,是Hive新的命令行客户端工具.Hive ...

  5. SpringMVC之@ControllerAdvice

    @ControllerAdvice ,很多初学者可能都没有听说过这个注解,实际上,这是一个非常有用的注解,顾名思义,这是一个增强的 Controller.使用这个 Controller ,可以实现三个 ...

  6. UWP使用命名管道与桌面程序通信 (C#)

    关于UWP的历史,其起源是Microsoft在Windows 8中引入的Metro apps.(后来又被称作Modern apps, Windows apps, Universal Windows A ...

  7. 【axios】API 说明

    基于promise用于浏览器和node.js的http客户端 特点 支持浏览器和node.js 支持promise 能拦截请求和响应 能转换请求和响应数据 能取消请求 自动转换JSON数据 浏览器端支 ...

  8. protected访问权限

    Java中protected方法访问权限的问题 protected 修饰的成员变量或方法,只能在同包或子类可访问; package 1 public class TestPackage { prote ...

  9. 【硬核摄影2.0】用线性CCD器件制作扫描相机

    本文参考资料:[1] (Strongly Recommend!) Fundamentals and Experiments of Line Scan Camera: http://www.elm-ch ...

  10. 前端 | 页面触底自动加载 Vue 组件

    不管是 web 端还是移动端,信息流都是现在很流行的信息展示方式.信息流经常搭配自动加载一起使用以获得更好的使用体验. 最近在使用 Vue 开发过程中也遇到了首页信息流自动加载的需求.大致了解了一下几 ...