变量声明
简短声明方法,使用:=,在函数内部使用,外部无法通过。
全局变量
使用var来定义。
函数调用
func 函数名 (int a, int b) (int c, int d)
input = a, b ;
output = c, d ;
函数其实在之前已经见过了,第一次执行hello world程序的main()其实就是一个函数,而且是一个比较特殊的函数。
每个go程序都是从名为main的package包的main()函数开始执行,包的概念不是这里的重点,以后做单独说明。同时main()函数是无参数,无返回值的。
注意点
小写字母开头的函数只在本包内可见,大写字母开头的函数才能被其他包使用。
同时这个规则也适用于变量的可见性,即首字母大写的变量才是全局的。
函数详解
具体参照:https://yushuangqi.com/blog/2013/ysqi-golang-function-1.html
func function_name( [parameter list] ) [return_types] {
函数体
}
type mytype int // 新的类型
func (p mytype) funcname(q int) (r,s int) {return 0,0}
定义解析:
从Go的函数定义可以看出,Go的返回值是放在函数名和参数后面的,这点和C及Java的差别还是很多大的。
func:Go的函数声明关键字,声明一个函数。
function_name:函数名称,函数名和参数列表一起构成了函数签名。
parameter list:参数列表,指定的是参数类型、顺序、及参数个数。参数是可选的,即函数可以不包含参数。参数就像一个占位符,这是参数被称为形参,当函数被调用时,将具体的值传递给参数,这个值被称为实际参数。
return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。这里需要注意的是Go函数支持多返回值。有些功能不需要返回值,这种情况下 return_types 不是必须的。
函数体:函数定义的代码集合,表示函数完成的动作。
在golang里面,使用go这个关键字,后面再跟上一个函数就可以创建一个线程。后面的这个函数可以是已经写好的函数,也可以是一个匿名函数。
那为什么会这样呢?因为程序会优先执行主线程,主线程执行完成后,程序会立即退出,没有多余的时间去执行子线程。如果在程序的最后让主线程休眠1秒钟,那程序就会有足够的时间去执行子线程。
指针使用
https://blog.csdn.net/whatday/article/details/74453089
goroutine:
Go语言是原生支持****语言级****并发的,这个并发的最小逻辑单元就是goroutine。goroutine就是Go语言提供的一种用户态线程,这种用户态线程是跑在内核级线程之上的,goroutine在运行时的调度是由Go语言提供的调度器来进行的,创建一个goroutine使用关键字go,go创建的goroutine不会阻塞主线程:
go func_name()
Go程序中没有语言级的关键字让你去创建一个内核线程,你只能创建goroutine,内核线程只能由调度器根据实际情况去创建。
调度器原理参考链接:**http://studygolang.com/articles/1855
channel:
Channel是Go中的一个核心类型,可以把它看成一个管道,通过它可以发送或者接收数据进行通讯(communication)。配合goroutine,就形成了一种既简单又强大的请求处理模型,即N个工作goroutine将处理的中间结果或者最终结果放入一个channel,另外有M个工作goroutine从这个channel拿数据,再进行进一步加工,通过组合这种过程,可以胜任各种复杂的业务模型。
channel的基本操作:
var c chan int //声明一个int类型的channel,注意,该语句仅声明,不初始化channel
c := make(chan type_name) //创建一个无缓冲的type_name型的channel,无缓冲的channel当放入1个元素后,后续的输入便会阻塞
c := make(chan type_name, 100) //创建一个缓冲区大小为100的type_name型的channel
c <- x //将x发送到channel c中,如果channel缓冲区满,则阻塞当前goroutine
<- c //从channel c中接收一个值,如果缓冲区为空,则阻塞
x = <- c //从channel c中接收一个值并存到x中,如果缓冲区为空,则阻塞
x, ok = <- c //从channel c中接收一个值,如果channel关闭了,那么ok为false(在没有defaultselect语句的前提下),在channel未关闭且为空的情况下,仍然阻塞
close(c) //关闭channel c
for term := range c {} //等待并取出channelc中的值,直到channel关闭,会阻塞
单向channel:
var ch1 chan<- float64 //只能向里面写入float64的数据,不能读取
var ch2 <-chan int //只能读取int型数据
select:
select用于在多个channel上同时进行侦听并收发消息,当任何一个case满足条件时即执行,如果没有可执行的case则会执行default的case,如果没有指定defaultcase,则会阻塞程序,select的语法:
select {
case communication clause :
statement(s);
case communication clause :
statement(s);
/可以定义任意数量的 case /
default : /可选 /
statement(s);
}
说明:
每个case都必须是一次通信
所有channel表达式都会被求值
所有被发送的表达式都会被求值
如果任意某个通信可以进行,它就执行;其他被忽略。
如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。
否则: 1.如果有default子句,则执行该语句。
如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。
package main
import (
"fmt"
"time"
)
func enqueue(q chan int) {
time.Sleep(time.Second * 3)
q <- 10
close(q)
}
func main() {
var c =make(chan int)
go enqueue(c)
for {
select {
casex, ok := <- c:
if ok {
fmt.Println(x)
} else {
fmt.Println("closed")
return
}
default:
fmt.Println("waiting")
time.Sleep(time.Second)
}
}
}
channel里的数据跟array一样,会fifo,不会黏在一起。
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
有疑问加站长微信联系(非本文作者)