golang学习笔记
前言:
由于进来事情繁多,blog好久没更新了。今天来一发。
最近在写一些golang的代码,它有很多优点,其中协程的概念,让golang有高并发能力,所以不少人用golang写service代码
1.一些基础
1.1
注释符:
/ /
//
1.2
开头必须是package声明,表示go属于的包
1.3
import 用于导入程序依赖包
1.4 fmt 为输出函数
fmt.Printf() %s--string %d--int %c---ch
其实我更喜欢go的log这个模块,这个模块可以写日志,可以做输出函数
1.5
func main(){
}
main()函数是入口点,没有参数,输入cmd输入的参数,在os.Args变量中保存,或者使用flag包,可以自定义输入的东西
注意:{ 这个花扣号要紧跟在main函数后面,不能换行,否则报错
1.6
无需分号
1.7
sublime是最好用的编辑器,它有golang的插件
2.数据类型
变量需要声明才能用,常见必如:
var v2=10
v3 :=10 //我喜欢用这个
const Pi float64=3.141592 //常量
2.1 布尔类型(bool):
v2 :=true //true false
2.2(int,float)整型和浮点型
2.3字符类型和字符串型
两个是不同的东西,但是容易混乱放一起来说吧:
字符类型(byte)
其实是 int,它是asii码对应到字符的
fmt.Println("hello"[1])//输出101,101是e的asii码
字符串(string)
var strs string
strs="wilson"
字符串我理解为字符类型的数组
字符串常见运算:1.拼接;x+y 2.字符长度;len(s),3.取字符 s[i]
go有strings模块来处理字符串类型,大家可以看这里:http://www.du52.com/text.php?id=454
2.4数组(array)和数组切片(list)
两个是概念相似,放一起来说吧:
声明:
[]类型{}
数组 array声明时候需要定义大小,定义完就不能改变了,所以一般我喜欢用切片
array:=[100]int{}
数组切片
类似于python的list可以变化长度,动态变化
slice :=[]int{}//其实区别就是[]有没有指点好,指点好了就是数组,长度不能变化,未指点为切片,长度可以变化
slice2:=make([]int,5)
2.5 字典(map)
就这是key-value的组合,编程时候经常用到这种类型的数据类型
var map1 = make(map[string]string)
map['key']="values"
注意:多协程操作map需要加上锁!
下面这个结构可以用来遍历字典,切片和数组:
for i,v :=range slice{
fmt.Println("slice[",i,"]=",slice3[i])
}
for k,v :=range map1{
fmt.Println(k,v)
}
3.控制流
条件判断中都不会有()的
条件:
if a<5{
return 1
}else{
return 0
}
循环:
for i:=0;i<=100;i++{
sum++
}
或者
for{
sum++
if sum>100{
break
}
}
4.函数
func xxxxfunc(参数列表) (返回值列表) {
//支持多值返回结果。
//无返回就为null,或者0
}
func Getname() (firstName,lastname,nickname string){
}
只是想得到nickname,就可以用匿名变量
_, _, nickname :=Getname
注意:这里传入的不会去改变本身的值,除非你是传入地址
5.面向对象与接口
面对对象编程是工程编程的非常重要的一个知识点。
类成员声明:
type Poem struct {
Title string
Author string
intro string
}
这样就声明了一个类,其中没有public、protected、private的的声明。
golang用另外一种做法来实现属性的访问权限:属性的开头字母是大写的则在其它包中可以被访问,否则只能在本包中访问。类的声明和方法亦是如此。
类方法声明:
func (poem *Poem) publish() {
fmt.Println("poem publish")
}
或者
func (poem Poem) publish() {
fmt.Println("poem publish")
}
这两者定义是有区别的:前者可改变类的里面变量,后者不行。。所以一般喜欢用前者
比如:下面这个,你会发现po一直原来的值,你再Publish里这么设置都没用。除非你传入是指针
package main
import "fmt"
type Poem struct {
Title string
Author string
intro string
}
func (poem Poem) Publish() {
fmt.Println("poem publish")
poem.Title = "xsseagle"
}
func main() {
po := Poem{"xss","wilson","xss"}
po.Publish()
fmt.Println(po)
}
6.并发编程
协程(gorountine)可以理解为轻量级的线程,系统可以开百万个协程。利用这个特点,我们可以写出很简单的代码,却能毫无压力的接受大并发的请求。
go funcname()
调用时候,是在新的goroutine中并发执行。
egg:
sockaddr := "0.0.0.0:3333"
func listentcp() {
tcpAddr, err := net.ResolveTCPAddr("tcp", sockaddr)
if err != nil {
log.Fatalln("net.ResolveTCPAddr 失败:", err.Error())
}
listen, err := net.ListenTCP("tcp", tcpAddr)
if err != nil {
log.Fatalln("监听端口失败:", err.Error())
} else {
log.Println("socket 已初始化连接,等待客户端连接...")
}
defer listen.Close()
for {
conn, err := listen.Accept()
if err != nil {
log.Println("接受客户端连接异常:", err.Error())
continue
}
defer conn.Close()
//再开启协程一直接受客户端的消息
go Recvmsg(conn, cli_ip)
}
}
func Recvmsg(conn net.Conn, cli_ip string) {
//10240 字符为上限
data := make([]byte, 10240)
for {
//阻塞,反复接受客户端的消息
i, err := conn.Read(data)
if err != nil {
log.Println(cli_ip, "链接断开,原因:", err.Error())
conn.Close()
break
}
msg := string(data[0:i])
log.Println(cli_ip, "发来数据:", msg)
}
}
还有channel概念,是用于协程之间的相互通信。由于精力有限不再详细写。
7.结语
关于golang:
由于本人精力有限,很多东西不能说透。如果你真心喜欢golang,想用它写出一个好东西。
那我的建议是去读一个golang工程,这里我建议去读这个:http://open-falcon.com/
学代码的最好方式就是去读别人的代码,这是我体会最深的道理了。读的多了就积累多了,积累多了那你写代码时候其实就是搬照之前你写过的代码了
其它话:
之前本来要写javaweb的mvc安全,可惜后来去实习了,没有继续研究javaweb mvc 安全。要是以后有机会研究时候一定再补上。
最后再祝大家新年快乐,学习进步,工作顺利。23333333
师傅已经全面掌握python、java、golang。
@phithon:求p总不黑 0.0