博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Go学习】Go(Golang)知识点总结
阅读量:235 次
发布时间:2019-03-01

本文共 14632 字,大约阅读时间需要 48 分钟。

1,Go介绍

是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。

1)环境搭建

①标准包安装

检查安装成功:在终端输入:go,出现go命令列表。

②配置环境变量

(1)打开终端,cd ~(2)查看是否有.bash_profile文件:		ls -all(3)有则跳过此步,没有则:   1)创建:touch .bash_profile   2)编辑:open -e .bash_profile   3)自定义GOPATH和GOBIN位置:export GOPATH=/Users/lwh/program/Goexport GOBIN=$GOPATH/binexport PATH=$PATH:$GOBIN(4)编译:source .bash_profile

终端输入以下命令。显示go运行所需的系统环境变量。

go env

③安装集成开发工具(LiteIDE、Sublime Text、Vim、Emacs、Eclipse、vscode、goland)

Sublime Text3的gosublime这个插件目前不能用,但是可以在github上下载,相比起来vscode有智能提示所以采用vscode。

goland使用:

goland应该是最好用的,很少的配置,收费,不缺钱可以支持下正版。
i> 。
ii> 新建一个project,选择项目location。
如果go环境安装成功goroot可以选择。然后create项目。
在项目根目录创建directory:main。然后在其下方写一个新的程序:test.go。

package mainimport (       "fmt")func main(){       fmt.Println("hello world")}

Control + shift + R运行即可。#

④工作空间

即创建GOPATH目录,并在GOPATH下建立三个目录:

bin:存放编译后生成的可执行文件(.exe)pkg:存放编译后生成的包文件(.a)src:存放项目源码(.go)

2,基本语法

1)常量、变量与命名规则

①可见性规则

函数名首字母小写,表示private;

函数名首字母大写,表示public。

②常量 const

运行期间不可改变值。

可以涉及计算,但每一个值必须是编译期就能获得。

1>内置常量

true、false、iota。

iota

初值为0,作为常量组中常量个数的计数器。

2>定义

const PI float32 = 3.1415926const PI = 3.1415926   //隐式类型常量定义(省略常量类型,根据赋值自动判断类型)const a,b,c = 1, "Go", 'c'  //整型常量、字符串常量、字符常量 多个常量一起定义

3>枚举

枚举指一系列的常量。

const (		Sunday  = iota //0  iota生成了从0开始自动增长的枚举值		Monday         //1  后续的iota可以省略		Tuesday        //2	)	const (		A = iota //iota每遇到一个const关键字,就重置为0		B	)	fmt.Println(Sunday);  //0	fmt.Println(Monday);  //1	fmt.Println(Tuesday); //2	fmt.Println("-------");	fmt.Println(A); //0	fmt.Println(B); //1

③变量 var

运行期间可改变的值。

变量名是用来引用变量所存储数据的标识符,实际上代表变量在内存中的地址,可以使用&获取。

1>定义

var count int = 10   //格式为:var 
[variableType]var count = 10 //缺省count: = 10 //用:代替var的缺省

2>变量的类型零值

即初始化值。

类型 零值
bool false
int、float、byte\rune 0
complex 0+0i
string “”
pointer、function、interface、slice、channel、map nil

④标识符命名规则

i> 以字母或下划线开始

ii> 由字母、数字、下划线组成
iii> 避免关键字
iv> 大小写区分为不同的变量

2)数据类型

①基本数据类型

1> 布尔型 bool (1 Byte)

取值范围:true | false。

2> 整型

进制(4种):

123  //十进制0123  //八进制 以0开头0x123  //十六进制  以0x开头1e3   //指数形式 由数字和e组成  1*(10^3) = 1000

有无符号整型:

int   //有符号整型uint //无符号整型

精度控制整数:

类型 字节长度 取值范围
int 4/8 由操作系统决定。32位机:int32,64位机int64
int8 1 -128~127 (- 2^7 ~ (2^7 -1) )
int 16 2 - 2^15 ~ (2^15 -1)
int 32 4 - 2^31 ~ (2^31 -1)
int 64 8 - 2^63 ~ (2^63 -1)
- - -
uint 4/8
uint8 1 -128~127 (- 2^8 ~ (2^7) )
uint 16 2 ……
uint 32 4 ……
uint 64 8 ……
字节型 byte(1byte) == uint8

本质是uint8的类型,使用效果完全一样。

使用该别名是为了增强代码的可读性,告知现在是进行字节处理。
主要作用:表示和存储ASCII码,即处理字符。

字符型

字符以ASCII的形式存储到内存中。所以一个byte型数据直接输出就是uint8整数形式;也可以将对应的ASCII码转换成相应的字符。

rune类型 == int32

Go语言处理Unicode时专门的数据类型,完全等价于int32。

使用该别名是为了增强代码的可读性,告知现在是进行Unicode字符处理。

3> 浮点型(实数)

表示形式:

1.251.23e3
类型 字节长度 精确位数
float32 32位浮点型 4 精确到小数点后7位
float64 64位浮点型 8 精确到小数点后15位

浮点数存在舍入误差,所以避免极大数和极小数相加减丢失极小数。

4> 复数型

var cp complex64 = 1.2 + 3.4i    //复数:a+bi形式的数(i = 根号-1)。real(cp)   //即1.2,fmt内置包计算实部的函数imag(cp)   //即3.4,fmt内置包计算虚部的函数
类型 字节长度
complex64 8
complex128 16

5> uintptr 指针类型

uintptr是可以保存指针的无符号整数类型,可以保存32位或64位的指针。根据操作系统决定指针位数。

//一般表现形式:var 
<指针变量名>
*
<基类型>
var i_pointer * int //指向整型的变量的指针i_pointervar i int = 100; i_pointer = &i //将i的内存地址存放到i_pointer中fmt.Println( * i_pointer ) //通过指针i_pointer读取对应地址存放的数据,结果输出为100。

使用注意:

  • 指针类型初始化默认值为nil,Go中没有NULL常量。
  • Go中不支持指针运算。
  • Go不支持运算符,直接用.选择符操作指针对象成员。

②值类型和引用类型

1>值类型

包括:bool、int、float、byte、复数型(complex)、字符串(string)、数组、结构体、错误类型(error)。

值拷贝传递。
字符串(string)、数组、结构体又称为构造类型。

2>引用类型

包括:指针、切片(slice)、字典(map)、通道(channel)、接口(interface)、函数(function)。

③字符串(string)

1> 字符串内容不可变

2> 字符串操作

var str string = "hello"; //字符串初始化	fmt.Println(str[2]);      //取字符,以0开始。'A' = 65,'a' = 97, 输出为l =  97+12 = 108	fmt.Println(len(str));    //len()函数  输出为5	fmt.Println(str + " world");

3>字符串遍历

支持2种方式。

var str string = "hello";	//字节数组方式遍历:(每一个字符类型为byte)	for i := 0; i < len(str); i++ {		fmt.Printf("str[%d] = %v\n", i, str[i]);	}	fmt.Println("-----------");	//Unicode字符方式遍历:(每一个字符类型为rune)	for i, ch := range str {      		fmt.Printf("str[%d] = %v\n", i, ch);	}

4>strings 包

Go标准库包。

包含了字符串查找函数、字符串比较函数、字符串位置索引函数、字符串追加和替换函数

5>strconv 包

Go标准库包。

提供了字符串与基本数据类型相互转化的基本函数。

④数组类型

1>定义

数组是一组具有相同类型和名称的变量的集合。

var arr1 [5] int

数组的元素类型必须是基本数据类型。

2>初始化

var arr1 = [2] int {1,2}	var arr2 = [2] int {1}	var arr3 = [...] int {2,2} //...就是三个英文句号。这个不能省略,否则就成切片了

3>多维数组

var a[3][4] int  //二维数组定义var a = [3][4] int {
{1,2,3}, {4,5}, {6}}

⑤切片(slice)(变长数组)

是数组的一个引用,它会生成一个指向数组的指针,并通过切片长度关联到底层数组部分或者全部元素。

切片还提供了一系列对数组的管理功能,可以随时动态的扩充存储空间,并且可以被随意传递而不会导致所管理的数组元素被重复赋值。
故切片通常用于实现变长数组。

1>切片原型

type slice struct {        array unsafe.Pointer      //Pointer 是指向一个数组的指针        len   int     //len 代表当前切片的长度        cap   int   //cap 是当前切片的容量。cap 总是大于等于 len 的    }

2>声明

var slice1 [] int  //不要指定数组长度即切片

3>初始化

默认为nil,长度为0.

var slice1 = [] int {1,2,3,4}var slice1 = make([] int, 4)  //通过内置函数make创建有4个元素的整型切片,元素初始值为int的初始值0.var slice1 = make([]int, 4, 10) //预留10个元素的存储空间。

4>操作数组

slice1 = array1         //指定切片引用范围为数组全部slice1 = array1[ : ]   //指定切片引用范围从第一个元素到最后一个元素slice1 = array1[m:n]  //指定切片引用范围从第m个元素到第n个元素

5>操作

  • 访问:利用下标
  • 元素增加:append()
  • 元素复制:copy()

⑥字典(Map,Dictionary,哈希表Hash table)

由键值对组成。

1>初始化和创建

未初始化时值为nil。

var map1 map[string] int {}   //创建并初始化。键用[]包起来。map1["key1"] = 1

或者用make函数

var map1 map[string] int      //创建map1 = make( map[string] int)   //初始化,给map1分配存储空间

2>访问和操作

查找:

var map1 = map[string]int{"key1": 100, "key2": 200}	v, OK := map1["key1"] //查找一个特定的键值对。如果key值存在,则将Key对应的Value值赋予v,OK为true。否则v=0,OK为false。	if OK {		fmt.Println(v, OK) //输出:100 true	} else {		fmt.Println(v)	}

删除:

delete(map1,"key1")

⑦通道类型

⑧错误类型

⑨类型别名

使用type关键字为类型定义别名。

type(		word uint //定义word是uint的别名		小数 float32 //Go支持UTF-8编程格式,所以定义时可用非英文字符。	)	var f 小数 = 3.14	var i word = 3	fmt.Println(f)	fmt.Println(i)

⑩类型转换

格式:<变量A>[:] = <变量A的类型>(<变量B>)

var a int	var f float32 = 3.14	a = int(f)   //如果变量A已经定义过了,可以省略`:`	b := int(f)  	fmt.Println(a)	fmt.Println(b)

3)运算符与表达式

①分号

用分号来终止语句,但这个分号可以由词法分析器扫描源代码过程中自动插入(给每一行末尾根据简单的规则进行判断是否需要加分号,所以出现了左大括号约定)。

②注释

//或/*   */

③位运算符

运算符 描述 说明
^ 取反
&
|
&^ 标志位清除运算符 从a上清除b上的标志位
<< 左移
>>
var a, b byte = 10, 4 //1010	fmt.Println(a)      //10b	fmt.Println(^a)     //11110101b   2^8-1-10 = 256-11 = 245	fmt.Println(a &^ b) //1010b 清除 10b = 1000b = 8 ;1010b 清除 100b = 不变 = 1010b = 10	fmt.Println(a << 1) //10*2 = 20

④通道运算符(< -)

详细用法可见通道。

4)输入输出

①标准输出函数:

1>Print

2>Println

3>Printf 格式化输出

原型:func Printf( format string, a...interface{} ) (n int, err error)

会返回输出的字节数和错误类型。

作用对象 格式字符 说明
- %v 以基本格式输出
- %#v 输出数据,同时也输出Go语法表示
- %T 输出数据类型
- %% 输出%
bool %t 输出布尔值true flase
int %b、%d、%o、%x、%X 以二进制、十进制、八进制、十六进制(小写)、十六进制(大写) 输出
int %c 以Unicode字符格式输出(否则直接输出为ASCII码)
int %q 输出的每个字符自动加单引号
int %U Unicode格式:U+1234 == U+%04X
浮点型、复数 %b 无小数部分、两位指数的科学记数法
浮点型、复数 %e、%E 科学计数法(小写e、大写E)
浮点型、复数 %f 有小数部分,但无指数部分
浮点型、复数 %g、%G 根据实际情况采用%e(%E)或%f
字符串、切片 %s 直接输出字符串或切片
字符串、切片 %q 输出字符串的同时加双引号
字符串、切片 %x、%X 每个字节用两字符的十六进制数表示
指针 %p 以0x开头的十六进制数表示
- + 输出数值正负号对%q(%+q)按ASCII码输出
- - 使用空格填充右侧空缺(默认为左侧)
- #
- ‘ ’
- 0 用前置0代替空格填补空缺
fmt.Printf("str[%d] = %v\n", i, str[i]);

②标准输入函数

1>Scan

原型:

func Scan(a ...interface{} )( n int, err error )

将使用空格分割的连续数据顺序存入到参数中(换行也被视为空格)。返回参数的数量n。

var a,b,c int	fmt.Scan(&a,&b,&c)

2>Scanln

原型:

func Scanln(a ...interface{} ) ( n int, err error)

同Scan,不同的是Scanln读取到换行符才终止录入。

3>Scanf

原型:

func Scanf( format string, a ...interface{} )( n int, err error}

按照格式化字符读取数据。

var a,b,c int	fmt.Scanf("%d,%d %d",&a,&b,&c)  //严格按照格式输入才可以读取,如‘1,2 3’	fmt.Print(a)	fmt.Print(b)	fmt.Print(c)

5)顺序结构程序

复合语句

用花括号{}将多条语句组合在一起。

复合语句中的定义的变量是局部变量,作用域为整个复合语句。

6)选择结构程序

①if-else

if 表达式1 {} else if 表达式2 {} else

注意:if语句块中不允许执行return语句。

②switch

switch 条件表达式 {case 常量1:       语句1      ……default:       语句n}或者:switch{case 条件表达1:    语句1      ……default:       语句n}

注意:

1>case语句后面不需要break,执行完自动跳出switch语句。
2>如果想执行完当前case后,继续执行下一个case,在case块最后面添加语句:fallthrough

var op byte = '+';	switch op {	case '+':		fmt.Println(1);		fallthrough	case '-':		fmt.Println(2)	}

7)循环结构程序

只有for循环,没有do和while循环。

注意for语句后面没有括号。

好的编程习惯:

  • 循环变量名尽量短,如:i, j, z, ix等。
  • 不要在循环中修改循环变量

①for基本循环结构

var str string = "hello";	for i := 0; i < len(str); i++ {		fmt.Printf("str[%d] = %v\n", i, str[i]);	}

执行顺序:表达式1,表达式2,表达式4,表达式3

for 表达式1; 表达式2; 表达式3 {      表达式4}

②for条件循环结构

类似while循环。

for 条件表达式{}

③for无限循环结构

用break跳出循环。

for{}for true{}for ; ; {}

④for range语句

相当于迭代器,可以对数组(Array)、切片(Slice)、字典(Map)、通道(Channel)等进行遍历。在遍历时会返回一个键值对。

var str string = "hello";	for i, ch := range str { //返回的键值对i,ch  i为下标,ch为值。		fmt.Printf("str[%d] = %v\n", i, ch);	}

可以使用占位符过滤掉不需要数据。

for _,ch := range str{}   //只需要值不需要键for i, _ := range str {}   //只需要键不需要值for i := range str {}   //只需要键不需要值

⑤跳转语句

1> goto

与LABEL搭配使用。

var a int = 1;	goto LABEL1	a++	LABEL1:		fmt.Println(a);

2> break

3> continue

8)函数

①包声明部分

包是组成的Go程序的基本单位。每个Go源代码都要进行包声明说明当前文件属于哪个包。

package 

可执行Go程序有且仅有一个main包,有且仅有一个main函数(在main包中)。

源码编译后都会生成*.a文件。

②第三方包导入部分

分为如下三种模式。导入的包没有使用编译会报错(保证代码体积小,加快编译速度)。

1>正常模式

import 

举例:

import "fmt" //导入包fmt.Println(v, OK) //输出:100 true   //包内函数调用

2>别名模式

包名相近或相同用别名区分。

import 别名 

3>简便模式

import . 

③函数声明部分

func为关键字。允许多返回值。

func funcName(参数列表)(返回值列表){       return result1, result2}

main函数没有参数也没有返回值,如果要传入参数,可在os.Args变量中保存。

④变参传递

任意数量:

func main() {	a(1,2,3,4,5);}func a(args ... int){ 	fmt.Println(args) //输出[1 2 3 4 5]	fmt.Println(args[2:]) //输出[3 4 5] 从索引2开始的数字}

任意类型的变参,类型指定为空接口interface{}:

func main() {	a(1,2,"s",4,5);}func a(args ... interface{}){	fmt.Println(args) //输出[1 2 s 4 5]}

⑤闭包(Closure)

内部函数通过某种方式使其可见范围超出了其定义范围。

在go语言中,闭包可以作为函数对象或匿名函数。确保只要闭包还被使用,那么被闭包引用的变量会一直存在。

⑥defer语句

通过defer向函数注册退出调用,当主调函数退出时,defer后的函数才会被执行(不管是否出现异常都会被执行)。

1>最后调用

defer fmt.Println("defer ")	fmt.Println("main ")

输出:

main defer

2>倒序输出

for i:=0; i<4; i++{		defer fmt.Println(i)	}

输出:3210

3>匿名函数调用

func main() {	fmt.Println("f1 = ",f1())	fmt.Println("f2 = ",f2())}//一个延迟执行的函数的变量的值在声明时,值不延迟func f1() int{	var i int	defer fmt.Println(i)	i = 1	return 1}//被延迟的匿名函数会读取f2的返回值,或对f2的返回值赋值func f2()(i int){	defer func(){		i++	}()	return 1}

4>用于清理工作

defer语句常用来进行函数的清理、释放资源等工作。

srcFile,err := os.Open("myFile")defer srcFile.Close

9)结构体

①使用

Go没有类的概念,通过结构体来实现面向对象编程。

type date struct {//定义	year int}type student struct {	id int	name string	birthday date}func main() {	stu := new(student)	stu.name = "a"    //访问	stu.id = 0	stu.birthday.year = 5	fmt.Println(stu)}
stu := student{0,"a",date{1}}  //对象初始化

②嵌入式结构

③匿名字段

④方法

1>定义

在普通的函数名前增加绑定类型参数。

type student struct {	id int	name string	fee int}type teacher struct {	id int	name string	fee int}func main() {	stu := student{0,"a",10}	t1 := teacher{0,"a",10}	fmt.Println(stu.getFee())	fmt.Println(t1.getFee())}func (revc student) getFee() int{    //rev为变量,student为struct类型。	return 10+100}func (revc teacher) getFee() int{    //类似java中的多态。接收类型不同,方法名可以一样	return 10+1000}

如果指针作为一个receiver,那么是一个引用传递。

2>匿名Receiver

3>继承和重写

type people struct {	id int	name string	fee int}type student struct {	people	school string}func main() {	stu := student{people{0,"a",10},"ut"}	fmt.Println(stu.getFee())}func (revc student) getFee() int{ //重写了方法,隐藏了people的getFee方法	return 10+100}func (revc people) getFee() int{	return 10+1000}

4>字段标签

10)接口(Interface)

是一组Method的组合,通过Interface来定义对象的一组行为。

①定义

type Speaker interface {  //关键字:type interface	sayHi()}func (s student)sayHi(){	}func (s student)study(){}

②接口组合

集合其他接口的功能

type SpeakerLearner interface {	Speaker	study()}

③空接口

表示任何数据类型。

interface{}

④使用

⑤反射

3,包

1)fmt

是format缩写。内置基本包。

Package fmt implements formatted I/O with functions analogous to C’s printf and scanf. The format ‘verbs’ are derived from C’s but are simpler.

2)math

①Min、Max

Max(int8)  Min(int8)  //数据的最大值最小值

3)strings包

4)strconv包

5)bytes包(字节切片标准库)

提供了对字节切片进行读写操作的一系列函数和方法。包括:字节切片处理函数、Buffer对象和Reader对象,类似于strings包。

6)bufio包

实现了对数据I/O接口的缓冲功能。

封装于接口io.ReadWriter、io.Reader和io.Writer中,在提供缓冲的同时实现了一些文本的基本I/O操作功能。

4,加强

1)内存分配机制

①源码文件

UTF-8格式。

②GC

标记-清除算法。

③内存函数

GO有两种分配内存机制,分别是使用内置函数new()和make()。

1>new()

用于给值类型的数据分配内存,调用成功后返回一个初始化的内存块指针,同时该类型被初始化为“0”.

2>make()

用于给引用类型分配内存空间。

make函数创建的是一个引用类型对象,而不是一个内存空间的指针。

2)并发程序设计

①基本概念

1>OS提供的并发基础

进程、

线程、
协程(用户态线程):不需要OS进行抢占式调度,在真正的实现中寄存于线程。

2>程序间的并发通信

  1. 锁原语操作
  2. 信号量机制
  3. 共享内存(Shared Memory)
    多个并发单位在同时访问共享内存时,必须使用互斥锁等相关机制,保证对共享内存的互斥访问。这早就程序设计复杂。
  4. 消息通信机制(Message Communication Mechanism)
    Go语言在处理程序的并发模型时,主要采用消息机制。
    消息机制规定每个并发单位是自包含的、独立的个体,并且都有自己的变量,这些变量不能在不同的并发单位之间共享。每个并发单位的输入输出只有一种:消息,即Channel。(类似进程的感觉)

②Goroutine(轻量级线程)

是Go语言运行库的功能(由Go运行时管理(Runtime)),不是OS提供的功能(不是用线程实现的,所以支持跨平台)。

Goroutine就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。因为节省了频繁创建和销毁线程的开销,所以对于进程、线程的开销非常小。可以轻松创建上百万个Goroutine,但它们不是被OS所调度执行的。
Go语言标准库提供的所有系统调用操作(包括同步I/O操作),都会让出处理机给其他Goroutine。

1>创建(与Channel一起使用)

通过关键字go来创建并发执行的Goroutine。

基本格式:go func()

import (	"fmt"	"math/rand")func Test(ch chan int){	ch <- rand.Int()  //随机数获取并写入	fmt.Println("Test")}func main() {	chs := make([]chan int , 10) //定义一个包含10个Channel的数组chs	for i:=0;i<10;i++{		chs[i] = make(chan int)		go Test(chs[i]) //启动10个Goroutine,对应每一个Goroutin分配一个Channel	}	for _,ch := range chs{		value := <-ch     //从通道读取数据		fmt.Println(value)	}	fmt.Println("main")  //因为通道的写入和读取都是阻塞的,从而保证了即使没有锁,所有的Goroutin执行完后才main才返回。即:main总是在最后输出的。}

③通道(Channel)

1>概念

是Go提供的消息通信机制。主要用于并发通信,类似于单双向数据管道(Pipe),用户可以通过Channel在两个或多个Goroutine之间传递消息。

注意:

  1. 同一时刻只有一个Goroutine能从Channel中接收数据,这就避免了互斥锁的问题。
  2. Channel中数据的发送和接收都是原语操作,不会中断,只会失败。

2>声明和初始化

Channel是引用类型,一个Channel只能传递一种类型的值,这个类型需要在声明Channel时指定。

支持的类型:基本类型、指针、Array、Slice、Map

var chanName chan ElementTypevar ch chan int   //一个传递int类型的Channel。chan为关键字。ch := make(chan int)   //用make函数直接声明

3>数据接收和发送

ch < - value      //通道接收数据。ch表示通道,value表示数据。value = < - ch  //通道发送数据

注意:

3. 向Channel写入数据通常会导致程序阻塞,直到有其他Goroutine从这个Channel中读取数据。
4. 如果Channel中之前没有写入数据,那么从Channel中读取数据也会导致阻塞,直到Channel中被写入数据为止。

4>close()

  1. 只有发送端才能关闭Channel,只有接收端才能获得关闭状态。
  2. close()调用不是必须的,但如果接收端使用range或者循环接收数据,就必须调用close(),否则报错:throw : all goroutines are asleep-deadlock!

5>单向通道

声明时可以将Chanel制定为单向通道:只能接收或只能发送。

var chanName chan <- ElementType  //只能接收var chanName <- chan ElementType //只能发送

6>异步通道

给Channel设定一个Buffer值,用于持续传输大量数据。

在Buffer未写满之前,不阻塞发送操作(即使没有读取方,发送方也不断写入数据);
在Buffer未读完之前,不阻塞接收操作。

ch := make(chan int, 1024) //创建一个大小为1024的int类型Channel。

7>select机制

主要用于解决通道通信中的多路复用问题。

select语句(类似switch):

select{	case <- chan1:   //如果 chan1 成功读取数据,则进行该case处理语句	case <- chan2:  	……	default:}

select直接检测case语句,每个case语句必须是一个面向Channel的操作.

只要其中一个case完成,程序就会继续向下执行。利用这个特性可以可以为Channe实现超时处理功能。

8>超时机制

由于通道的接收是阻塞式的,为了将阻塞式的通信转换为非阻塞式,将select机制和超时机制配合使用,以提高系统通信效率。

在Go语言并发编程的通信过程中,所有错误处理都由超时机制来完成。
超时机制一般用来解决通信死锁,通常设置一个超时参数,通信双方如果在设定的时间内仍然没处理完成任务,则该处理过程会立即被终止,并返回对应的超时信息。
Go没有提供直接的超时处理机制。利用select机制可以实现。

3)网络编程

传统的Socket网络编程分为:流式套接字(基于TCP)、数据报套接字(基于UDP)、原始式套接字(基于IP)。

①Dial()

Go语言对socket进行了封装,无论期望用什么协议都只需要调用Dial函数即可。

支持网络协议:tcp、tcp4、tcp6、udp、udp4、udp6、ip、ip4、ip6。
创建连接:

func Dial ( net, addr string) (Conn, error)  //net是网络协议名,addr是IP地址或域名,后面可跟随端口号。conn,err := net.Dial ("tcp", "192.168.0.1:5000")conn,err := net.Dial ("ip4:icmp", "www.baidu.com")

发送数据:使用conn对象的Write()方法

接收数据:使用conn对象的Read()方法

转载地址:http://ouqt.baihongyu.com/

你可能感兴趣的文章