Go语言的变量、函数、Socks5代理服务器示例详解
Go语言中变量的声明和JavaScript很像,使用var关键字,变量的声明、定义有好几种形式
1.变量和常量
//声明并初始化一个变量 varmint=10 //声明初始化多个变量 vari,j,k=1,2,3 //多个变量的声明(注意小括号的使用) var( noint namestring ) //声明时不指明类型,通过初始化值来推导 varb=true//bool型 //:=隐含声明变量并赋值 str:="mimvp.com"//等价于varstrstring="mimvp.com"
Go语言中=和:=有什么区别?
=是赋值,:=是声明变量并赋值
//=使用必须使用先var声明例如: vara a=100 //或 varb=100 //或 varcint=100 //:=是声明并赋值,并且系统自动推断类型,不需要var关键字 d:=100 //Go中有一个特殊的变量下划线"_"表示任何赋给它的值将被丢弃 _,Ret:=2,3//2赋值被丢弃
Go语言的编译器,对声明却未使用的变量在报错,因此变量声明了就必须使用,如果要使用变量也必须先声明
Go语言和C语言一样,Go语言中也是使用分号来终结语句。但是和C语言不同的是,Go语言的词法分析器在扫描源代码的过程中使用简单的规则自动插入分号,因此在编写源代码的多数时候就不需要加分号了
Go语言词法分析器插入分号的规则:如果在一个新行前方的最后一个标记是一个标识符(包括像int和float64这样的单词)、一个基本的如数值这样的文字、或以下标记中的一个时,会自动插入分号
Go语言通常仅在for语句中使用分号,以此来分开初始化器、添加和增量。还有一种情况就是当你在一行中写了多个语句,也需要使用分号来分开
由于Go语言词法分析器添加分号的特殊性,所以在有些情况下需要注意:
你都不应该将一个控制结构(if、for、switch或select)的左大括号放在下一行。
如果这样做,将会在大括号的前方插入一个分号,这可能导致出现不想要的结果。
常量:在程序不能被改变的值,一般都定义为数值,布尔值,字符串等
格式:constconstName[type]=val
1).varnum=3//实际上3也称为常量
2).格式中val可以是表达式,但不能为运行时才能知道结果的表达式
3).预定义常量:true/false/iota
4).定义多个常量时,也可用下面方式
const( constName1[type]=val1 constName2[type]=val2 )
示例代码:
/**
*mimvp.com
*2017.1.20
*/
//声明当前文件所属的包名,main是一个可独立运行的包,编译后会生成可执行文件
packagemain
import"fmt"//导入包
varid=123456
/*
id2:=654321
//在函数外用:=,编译时会出现错误,局部变量声明应在函数内部
//non-declarationstatementoutsidefunctionbody
*/
constPI=3.14//常量声明
//每个可独立运行的程序,都包含入口函数main,与其他语言相同,但无参数和返回值
funcmain(){
varnumint
num=100
fmt.Println(num)//输出100
varnum1,num2int
num1,num2=1,2
fmt.Println(num1,num2)//输出12
varno1,no2=3,4
fmt.Println(no1,no2)//输出34
n1,n2:=5,6
fmt.Println(n1,n2)//输出56
_,n:=7,8
fmt.Println(n)//输出8
var(
key1string
key2string
)
key1,key2="k1","k2"
fmt.Println(key1,key2)//输出k1k2
var(
a=9
b=10
)
fmt.Println(a,b)//输出910
fmt.Println(id)//输出123456
fmt.Println(PI)//输出3.14
/*
PI=3.1415
//改变常量的值,编译会出现错误
//cannotassigntoPI
//cannotuse3.1415(typefloat64)astypeidealinassignment
*/
}
2.函数使用
1)Go语言函数格式
funcGetMsg(iint)(strstring){
fmt.Println(i)
str="hellomimvp.com"
returnstr
}
解释说明:
func说明这是个函数
GetMsg是函数名
(iint)函数接收一个int参数,是传入参数
(strstring)函数返回一个string类型返回值,是返回参数
2)Go语言函数可返回多个值
函数返回多个值,跟Java、PHP、C等主流语言都不一样,但和Python、lua等脚本语言是一样的
vimmimvp_func.go funcGetMsg(iint)(strstring,errstring){ fmt.Println(i) str="hellomimvp.com" err="noerr" returnstr,err } funcmain(){ fmt.Println(GetMsg(100)) }
编译执行:
$gobuildmimvp_func.go $./mimvp_func 100 hellomimvp.comnoerr
3)defer的使用
defer的意思是"在函数退出时调用",特别用于对文件进行读写操作的时候,需要在open之后要调用close操作,将close操作使用defer
funcReadFile(filePathstring)(){
file.Open(filePath)
deferfile.Close()
iftrue{
file.Read()
}else{
returnfalse
}
}
上述代码含义是在file.Open后不立即调用close,当returnfalse的时候调用file.Close(),这样就有效避免了C语言中的内存泄露问题。
4)理解panic,recover
上面讲述了很多变量和函数,还没介绍throw-try-catch的用法
Go语言里,Panic和Recover就是其他语言中的throw和catch
示例代码:
packagemain
import"fmt"
funcmain(){
f()
fmt.Println("Returnednormallyfromf.")
}
funcf(){
deferfunc(){
ifr:=recover();r!=nil{
fmt.Println("Recoveredinf",r)
}
}()
fmt.Println("Callingg.")
g(0)
fmt.Println("Returnednormallyfromg.")
}
funcg(iint){
ifi>3{
fmt.Println("Panicking!")
panic(fmt.Sprintf("%v",i))
}
deferfmt.Println("Defering",i)
fmt.Println("Printinging",i)
g(i+1)
}
运行结果:
$./mimvp-try-catch Callingg. Printinging0 Printinging1 Printinging2 Printinging3 Panicking! Defering3 Defering2 Defering1 Defering0 Recoveredinf4 Returnednormallyfromf.
Panic抛出了信息,并且跳出函数。Recover接受到了信息,并且继续处理。
这个例子理解了基本就掌握了Recover和Panic
3.Socks5代理服务器
packagemain
import(
"net"
"fmt"
"io"
"bytes"
"encoding/binary"
)
typeMethodsstruct{
ver,nmethodsuint8
methodsuint8
}
typesock5cmdstruct{
ver,cmd,rsv,atypuint8
dst[255]uint8
}
typeproxyCoderstruct{
connnet.Conn
}
func(c*proxyCoder)readMethods()Methods{
varmMethods
b:=make([]byte,1024)
n,err:=c.conn.Read(b)
iferr!=nil&&err!=io.EOF{panic(err)}
buf:=bytes.NewBuffer(b[0:n])
err=binary.Read(buf,binary.LittleEndian,&m.ver)
iferr!=nil{
fmt.Println("binary.Readfailed:",err)
}
err=binary.Read(buf,binary.LittleEndian,&m.nmethods)
iferr!=nil{
fmt.Println("binary.Readfailed:",err)
}
err=binary.Read(buf,binary.BigEndian,&m.methods)
iferr!=nil{
fmt.Println("binary.Readfailed:",err)
}
returnm
}
func(c*proxyCoder)returnMethod(){
buf:=make([]byte,2)
buf[0]=5
buf[1]=0
c.conn.Write(buf)
fmt.Println(buf)
}
func(c*proxyCoder)serve(){
buf:=make([]byte,128)
n,err:=c.conn.Read(buf)
iferr!=nil&&err!=io.EOF{panic(err)}
fmt.Println(buf[:n])
varsstring
vartstring
variint
if(buf[3]==3){//domail
fori=4;i
总结
以上所述是小编给大家介绍的Go语言的变量、函数、Socks5代理服务器,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!