golang

go语言特性:

◆ 自动垃圾回收

具备系统自动释放资源

◆更丰富的内置类型

map类型、slice类型(类似vector)

◆函数多返回值

跟lua/erlang一样,支持函数多返回值,优化输入输出参数、结构体参数等传递

◆错误处理

defer/recover/panic,

defer用于资源的释放,go语言不提供构造和析构,

recover截取错误处理流程,一般在使用defer的关键字函数中使用;若在无异常的goroutine中使用recover,会导致此goroutine所在的进程打印错误信息后,直接退出

◆匿名函数

a := fun() / a();

◆类型、接口

类型struct,类似C的结构体,但不支持继承和重载;

接口:非入侵式接口、interface{}作为函数参数,可传递任何类型

◆并发

吸取erlang语言的面向消息编程机制,所有的数据交互都用goroutine的消息传递

◆反射

模仿java语言的反射特性,但不像java内置类型工厂

◆语言的交互性

go语言通过Cgo库,可混合编写C语言代码

golang并发:

        golang为实现高并发性,引入了goroutine,通过channel模式用CSP(通信顺序进程,Communicating
Sequential Process)模型实现goroutine之间的数据交互;

        golang的并发系统,由N个并行运行的CSP组成,每个CSP之间都是资源独立的,通过go提供的通信原语进行消息传递,通过类似管道的channel模式,来实现CSP,从而达到跨越goroutine的通信。

        此外,一个进程中的所有协程goroutine都在同一个内存空间中,所以不同的goroutine要去访问共享的内存变量时,需要访问读写锁,由go语言的sync库提供读写锁功能。

 

作用域:

小字母开头命名,只包内可见

大字母开头命名,包内外可见

适用于变量、类型、函数

 

go内置数据类型:

◆ 布尔bool

bool类型值只有true、false,不能复制为数值1、0等

◆ 整型:

int8/byte(uint8)/int16/uint16/int32/uint32/int64/uint64/int/uint/uintptr

int/uint:平台相关,32位4字节,64位8字节

uintptr :平台相关指针

int、int32 :go语言认为是两种类型,go语言不支持隐式类型转换,而且不支持不同类型的比较,比较必须是严格的“相同”类型,类型转换必须显示强转;若比较int32和int16类型的,编译器会报错;给变量赋值时,a
:= 12、b := 12.0会对变量类型进行自动推导,a为整型,b为浮点型。

◆ 浮点型float32/64

v1 := 12.0,系统进行自动推导时,v1为float64类型的

◆ 复数complex64/128

数学上的复数:3.2 + 12i,具备实部与虚部的概念

◆ 字符串string

go语言的string类型是内置的

◆ 字符rune

byte(uint8) : 代表utf-8的字符类型,占一个字节

rune : 代表Unicode字符,go标准库的unicode包提供相关操作,unicode/utf-8的包提供unicode/utf-8之间的转换

◆ 错误error

◆ 指针pointer

◆ 数组array

[32]byte
// 长度为32的数组,每个元素为一个字节

[2*N] struct{ x, yint32} //复杂类型数组

[1000]*float64//指针数组

[3][5]int
// 二维数组

[2][2][2]float64//等同于[2]([2]([2]float64))

注意:数组是值类型,故作为函数参数传递时,是值传递,传递的是一个数组的副本,即作为函数参数传递的数组是无法被修改的

◆ 切片slice

类似vector,具备cap容量的概念

slice的创建:创建、基于数组创建、基于切片创建

myArr := {1,2,3,4,5}

mySlice := myArr[:5]        //myArr[first : last],用myArr的前5个元素创建Slice

mySlice := make([]int, 5)   //创建5个为0的Slice

mySlice := make([]int, 5, 10)   //len(mySlice)是5,cap(mySlice)是10

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

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

newSlice := oldSlice[:6] ==>若oldSlice的元素个数不足,用0补全newSlice

slice的append:切片内容的附加

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

mySlice = append(mySlice, 1,2,3)    //第二个参数以右边的是不定参数类型

mySlice2 := []int{8,9,10}

mySlice = append(mySlice, mySlice2 ...)

//不定参数,省略号;第二个参数mySlice2后面加了三个点,即一个省略号,如果没有这个省

略号的话,会有编译错误,因为按append()的语义,从第二个参数起的所有参数都是待附加的

元素。因为mySlice中的元素类型为int,所以直接传递mySlice2是行不通的。加上省略号相

当于把mySlice2包含的所有元素打散后传入。

上述调用等同于:

mySlice = append(mySlice, 8, 9, 10)

数组切片会自动处理存储空间不足的问题。如果追加的内容长度超过当前已分配的存储空间

(即cap()调用返回的信息),数组切片会自动分配一块足够大的内存。

slice内容复制:copy(dstSlice, resSlice)

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

slice2 := []int{5, 4, 3}

copy(slice2, slice1) //只会复制slice1的前3个元素到slice2中

copy(slice1, slice2) //只会复制slice2的3个元素到slice1的前3个位置

◆ 字典map

==========================================================================

package main

import "fmt"

// PersonInfo是一个包含个人详细信息的类型

type PersonInfostruct{

ID string

Name string

Address string

}

func main(){

var personDB map[string] PersonInfo

personDB = make(map[string] PersonInfo)

personDB["12345"] = PersonInfo{"12345", "Tom", "Room 202, ..."}

personDB["1"] = PersonInfo{"1", "Jason", "Room 101, ..." }

person, ok := personDB["1234"]

if ok{

fmt.Println("Found person", person.Name, "with ID 1234.");

} else {

fmt.Println("Did not find person whit ID 1234.")

}

}

==========================================================================

var myMap map[string] PersonInfo

myMap = make(map[string] PersonInfo)

 

myMap := make(map[string] PersonInfo)

myMap := make(map[string] PersonInfo, 100)     
//预留100个PersonInfo空间

delete(myMap, "1234")

delete(myMap, nil) ==>编译器报错

 

◆ 通道 chan

◆ 结构体struct

◆ 接口interface

 

go变量与常量

◆ 变量

var v1 int = 10

var v2 = 10

v3 := 10

var i int              var i int

i := 2     ==>编译器报错   i = 2  ==>正确

i, j = j, i     //多重赋值 ==> C++: t = i; i = j; j = t;

_, _, nickName := GetName()     //匿名变量 "_"

◆ 常量

字面常量:无类型的,只要在值域范围内,就可以作为该类型常量

-12         //整型常量,-12可以赋值给int、uint、int32/64、float32/64、complex64/128

3.14            //浮点型常量

3.2+12i     //复数型常量

true            //布尔型常量

"str"       //字符串常量

常量定义:const关键字

const Pi float64 = 3.14159265358979

const (

size int64 = 1024

eof = -1

)

预定义常量:true、false、iota

iota比较特殊,可以被认为是一个可被编译器修改的常量,在每一个const关键字出现时被

重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1。

从以下的例子可以基本理解iota的用法:

const (      // iota被重设为0

c0 = iota      // c0 == 0

c1 = iota        // c1 == 1

c2 = iota                   // c2 == 2

)

const (

a = 1 << iota         // a == 1 (iota在每个const开头被重设为0)

b = 1 << iota         // b == 2

c = 1 << iota         // c == 4

)

 

const (

Sunday = iota

Monday

Tuesday

Wednesday

Thursday

Friday

Saturday

numberOfDays // 这个常量没有导出

)

go流程控制

◆ if

===================================================================================

if a > 0 {

}

if i :=0; i < 0{

}

func exfunc(x int) int{

if x == 0 {

return 5    ==>编译器报错

} else {

return x       ==>编译器报错,不允许在函数体内的“if等”语句体内使用return

}

}

===================================================================================

◆ switch : case 不支持break

◆ for : 不支持逗号多重赋值,支持continue、break控制循环

===================================================================================

for j := 0; j < 5; j++{

for i := 0; i < 10; i++{

if i > 5{

break JLoop

}

}

}

JLoop: ...

===================================================================================

===================================================================================

for i := 0; i < len(arr); i++{

...

}

for i, v := range arr{

...

}

===================================================================================

===================================================================================

for i := 0; i < len(mySlice); i++{

...

}

for i, v := range myslice{

...

}

===================================================================================

===================================================================================

func myfunc(args ...int){//...type格式类型(syntactic sugar),只作为函参存在,且是最后一个参数

for _, arg := range args{

fmt.Println(arg)

}

}==>myfunc(2,3,4);myfunc(4,5,6,4,65)

===================================================================================

◆ goto

func myfunc(){

i := 0

HERE:

fmt.Println(i)

i++

if i < 10 {

goto HERE

}

}

go函数

◆ 函数定义

 

◆ 函数调用

 

◆ 不定参数

===================================================================================

func myfunc(args ...int){       //接受不定数量的参数,全部为int

for _, arg := range args{

fmt.Println(arg)

}

}==>myfunc(2,3,4);myfunc(4,5,6,4,65)

//...type格式类型,本质是一个slice, []type

func myfunc(args ...int){

myfunc3(args ...)

myfunc3(args[1:] ...) int

}

fmt.Printf()的函数原型

func Printf(format string, args ... interface{}){  
//interface{}传递任意类型数据

...

}

◆ 多返回值

◆ 匿名和闭包

 

go错误处理

◆ defer

◆ recover

◆ panic

◆ error

 

 

6g, 6l  ==>  6go, 6link  64位,编译,link

8g, 8l  ==>  8go, 8link  32位,编译,link

gccgo

>7.1 version GDB  ==> gdb calc   DWARFv3

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-12 18:16:47

golang的相关文章

golang []byte转string

golang中,字符切片[]byte转换成string最简单的方式是 package main import ( "fmt" _ "unsafe" ) func main() { bytes := []byte("I am byte array !") str := string(bytes) bytes[0] = 'i'//注意这一行,bytes在这里修改了数据,但是str打印出来的依然没变化, fmt.Println(str) } 打印信息:

golang实现Ringbuf

Ring buffer算法优点:高内存使用率,在缓冲buffer内存模型中,不太容易发生内存越界.悬空指针等 bug ,出了问题也容易在内存级别分析调试.做出来的系统容易保持健壮. package main import ( "bytes" "fmt" ) type Ringbuf struct { buf         []byte start, size int } func New(size int) *Ringbuf { return &Ringb

Golang Hash MD4

//Go标准包中只有MD5的实现 //还好,github上有MD4实现. package main import (     "golang.org/x/crypto/md4"     "encoding/hex"     "fmt" ) func get_md4(buf []byte) ([] byte) { ctx := md4.New() ctx.Write(buf) return ctx.Sum(nil) } func main() {

Java程序员的Golang入门指南(上)

Java程序员的Golang入门指南 1.序言 Golang作为一门出身名门望族的编程语言新星,像豆瓣的Redis平台Codis.类Evernote的云笔记leanote等. 1.1 为什么要学习 如果有人说X语言比Y语言好,两方的支持者经常会激烈地争吵.如果你是某种语言老手,你就是那门语言的"传道者",下意识地会保护它.无论承认与否,你都已被困在一个隧道里,你看到的完全是局限的.<肖申克的救赎>对此有很好的注脚: [Red] These walls are funny.

golang学习笔记:golang 语法篇(二)

在语法篇(一)中学习了go中基本的数据类型.变量.常量等组成语言的基本要素,在这一节中将会学习如何将这些元素组织起来,最终写成可以执行的代码. 在这一部分包括: go中的流程控制语句: go中函数的用法: go特殊的错误处理方式: Golang中的流程控制语句 在具体编程的时候免不了需要使用一些特殊的语句实现某些功能,比如使用循环语句来进行迭代,使用选择语句控制程序的执行方式等.这些语句在任何一门程序设计语言 中都会有支持,golang中除了支持常用的循环,条件选择语句以外,还支持跳转语句,下面

Golang关键字—— if/else

Golang中,if/else 关键字用于条件判断,如果满足条件就做某事,否则做另一件事: if age >= 18 { fmt.Println("成年人") } else { fmt.Println("未成年") } 多重判断: if score >= 90 { fmt.Println("优秀") } else if score >= 70 { fmt.Println("良好") } else if sco

golang控制channel的出入口

golang控制channel的出入口 我们常常使用channel来在多个goroutine之间做数据通讯,但是chan作为函数的入参我们应该怎么写呢?也许有人觉得这个问题比较傻,不过这个还真的是我今天才知道的. 首先我们看看下面的代码: func main() { c := make(chan int) go in(c) go out(c) time.Sleep(time.Second) } func in(c chan int) { for i := 0; i < 10; i++ { c <

golang winForm开发

最近一直在看rust,语法挺头疼的,正好趁着1.0发布前的一段时间,回来玩玩golang. golang的语法很简单,liteIde又变得越来越好用,因此学习golang不会花费您多少时间,还能够清醒被rust晃晕的头脑,哈哈. winform开发虽然已经不再流行,但是用来练手却非常合适,写小工具也很爽,废话少说,golang的UI库就是大名鼎鼎的 andlabs ui, 在github的star数已达到1946,相当可观.这是一个跨平台的UI库,可以运行在 windows/linux/mac上

golang性能监控初探

最近在用golang写一个server.压力测试过程发现反应比较慢,但是由于中间的操作都是串行的,无法知道在哪个操作消耗了比较多时间. 一开始想到的是打log.但是单个请求又是很快的,于是想到如下方案 在调用每个函数的时候,统计该函数的时耗,然后利用channel把同一个函数调用发送到同一个地方,利用map进行累计统计(这里可以更近一步,比如统计每个worker甚至每个services的状态,包括最长请求时间,最短请求时间,平均消耗等等,如果加上runtime还可以记录其他的运行相关信息). 一

GoLang入门-安装-配置

Go的三种安装方式 Go有多种安装方式,你可以选择自己喜欢的.这里我们介绍三种最常见的安装方式: Go源码安装:这是一种标准的软件安装方式.对于经常使用Unix类系统的用户,尤其对于开发者来说,从源码安装是最方便而熟悉的.Go标准包安装:Go提供了方便的安装包,支持Windows.Linux.Mac等系统.这种方式适合初学者,可根据自己的系统位数下载好相应的安装包,一路next就可以轻松安装了.第三方工具安装:目前有很多方便的第三方软件包工具,例如Ubuntu的apt-get.Mac的homeb