半小时Golang开发入门

01

为什么用Golang?

当您启动新项目时,开发人员团队会召开几次会议进行技术选型,以决定合适的语言、框架以及架构。关于语言一般根据项目以及团队的特点选择最合适的,比如:Java、PHP、JavaScript、Golang、Python 或 C++,或者是几种组合。例如很多公司已经有Java技术架构的规范和基础,往往他们会直接使用Java,毕竟语言是为开发人员服务的。

Go 是 Google 于 2009 年创建的。并且这几年流行度增长快速,许多互联网公司也已经在前几年就开始招聘Go开发人员,例如:360直播在招聘Golang开发工程师。美团、滴滴、新浪以及七牛等。那么Go到底有什么优势呢?

Go提供了许多如方法和运算符重载、类型指示器、继承类型和指针运算。Go语言开发效率非常高,并且其系统运行性能相当出色。这些取决于一些它独到的优势:

  • 强类型和垃圾收集

  • 极快的编译时间

  • 内置并发控制

  • 丰富的标准库

02

Golang可用来做啥?

由于Golang是基于C开发的,代码运行效率比较高(比java、Python等都高),并且代码可根据运行平台类型直接编译成可执行文件,Golang开发的程序支持在Arm、X86平台上的各种操作系统,包括Linux、Windows、MacOS、Android、IoS。当然任何语言都有其产生的背景、优势、弱势,以下就是是它擅长的部分:

  • 服务器编程:例如处理日志、数据打包、虚拟机处理、文件系统等。

  • 分布式系统、数据库代理器、中间件。

  • WEB编程:Go在Web应用开发方面的应用是最广泛的,Go的web框架十分丰富,例如gin、beego等。

  • 开发云平台:许多云平台都是用Go开发的,例如七牛云、华为云等等都有使用Go进行开发并且开源的成型的产品。

  • 开发物联网:也是依赖于Golang的跨平台能力和网络能力。

  • 区块链:很多的区块链的系统和应用都是采用Go进行开发的,比如ehtereum是目前知名度最大的公链,fabric是目前最知名的联盟链,两者都有go语言的版本,且go-ehtereum还是以太坊官方推荐的版本。

当然,除了以上这些场景之外是Go擅长的之外,其实Golang还能开发移动应用、命令行程序、桌面系统。

03

安装开发环境

(1) 进入Golang官网,根据操作系统下载Go语言环境, 在MacOS下可以使用brew install go命令进行安装。

半小时Golang开发入门插图1

(2) 配置Go环境变量

  • 查看、配置GOPATH(使用MOD模式开发可以不用配置)

查看环境变量go env查看 GOPATH变量go env GOPATH

半小时Golang开发入门插图3

半小时Golang开发入门插图5

设置新的GOPATH

export GOPATH="/Users/zgq/go"

至于其他变量暂不做介绍

(3)Helloworld

在GOPATH路径下的src目录下(我的是/Users/zgq/go/src) 新建一个go代码:helloworld.go

//定义个包名,文件夹和包名可以一致,也可不一致package main//导入一个打印支持的包GO自带的输出import "fmt"//一个go文件的运行入口是main方法func main() {//打印输出,后面‘ ;’可有可无,go语言追求一种简洁和高效性fmt.Println("hellword")}

运行go脚本

go run helloworld.go

半小时Golang开发入门插图7

(4) 开发工具

这里我们选择vscode

安装vscode

安装vscode插件:

github.com/ramya-rao-a/go-outlinegithub.com/acroca/go-symbolsgolang.org/x/tools/cmd/gurugolang.org/x/tools/cmd/gorenamegithub.com/josharian/implgithub.com/rogpeppe/godefgithub.com/sqs/goreturnsgithub.com/golang/lint/golintgithub.com/cweill/gotests/gotests

半小时Golang开发入门插图9

在GOPATH/src下新建一个文件夹hello,并用vscode打开它。并新建一个main.go 的代码。写上几个简单的代码。

半小时Golang开发入门插图11

接下来配置启动项launch.json,并运行看看。

半小时Golang开发入门插图13

{"version": "0.2.0","configurations": [{"name": "server","type": "go","request": "launch","mode": "auto","program": "${workspaceFolder}/main.go"}]}

接着就可以打断点进行调试运行了。

半小时Golang开发入门插图15

如果是使用Mod模式的话需要设置golang env 参数

exportGO111MODULE = “on”

export  GOPROXY =“https://goproxy.cn”

在刚才的hello项目目录下执行:

go mod init hello

创建一个hello 为包名的项目,采用mod模式的项目目录可以不用在GOPATH目录下。

除了使用go run main.go 来运行go脚本之外,还可以将代码编译成可执行文件。

go build

半小时Golang开发入门插图17

04

语言结构

    4.1 基础语法

    • 变量

    go语言的变量定义可以使用

    var  name string

    也可以直接创建

    name:="zgq"

    注意:一般情况下变量名称字母大写表示包外部或者类外部可访问,首字母小写表示局部可访问。函数名称也类似。

    • 程序入口

    每个Go程序的入口都是main函数

    funcmain(){}

    基本的代码结构如:

    //包名,这个是必须的,同一个文件夹下必须相同包名package main// 导入包import("fmt")//程序入口funcmain(){fmt.Println("hello")}

      • make 和 new

      make创建一个变量

      new厂家一个变量的指针

      使用符号&获得指针,使用符号*获得变量

      //make 一个数组varstr =make([]string,2)str[0]="first"str[1]="second"fmt.Println(str)//new 一个数组的指针varstr_p =new([]string)*str_p =append(*str_p,"first")*str_p =append(*str_p,"second")fmt.Println(str_p)

      输出结果分别是:

      [first second]

      &[first second]

    4.2 数据类型

    //几个比较常用的原始类型vara stringvarb intvarc int32vard int64vare float32varf float64varg bool//数组//创建字符串数组vararr = []string{"a","b","c"}//数组截取arr2:=arr[1:2]//barr3:=arr[1:]//b,carr4:=arr[:1]//a,b//也可以使用make创建数组vararr = make([]string,0)//创建一个长度为0的数组arr = append(arr,"a")//添加元素//也可以用new创建对象指针vararr_p =new([]string)*arr_p = append(*arr_p,"first")//map类型varm = map[string]string{"name":"zgq","phone":"1245"}//也可以使用make创建后再赋值varm=make(map[string]string)m["name"]="zgq"//也可以使用new创建对象指针varmm =new(map[string]string)

    4.3 判断

    • if判断

    //比较ifa==b {}ifa>b {}ifa>=b {}ifa}ifa<=b {}//true、falsec := a==bifc {}//或ifa==b || a==c {}//与ifa==b && a==c {}//非if!(a==b) {}

    • switch 判断

    cc :=1switchcc {case1:fmt.Println("cc is 1")case2:fmt.Println("cc is 2")default:fmt.Println("cc is other")}

    4.4 循环

    • for循环

    //条件循环fori :=0; i <10; i++ {fmt.Println(i)}//数组循环arr := []string{"a","b","c"}for_, aa :=rangearr {fmt.Println(aa)}//map循环m :=map[string]string{"name":"zgq","phone":"1245"}forkey, val :=rangem {fmt.Println(key,"=", val)}

    4.5 函数

    函数用func 定义,例如:

    //没有返回值funcexec(a string,b int){......}//一个返回值funcexec(a string,b int) string{......return"result"}//多个返回值,用挂号组合func exec(a string,b int) (string,error){......return"result", err}

    初始化函数init

    go文件中如果存在init函数,将在运行初期被自动执行

    funcinit(){}

    4.6 接口

    • 类型

      类型定义,使用 type *** struct

    //类型定义type FileServiceImplstruct{//属性定义NamestringPathstring}//函数func (f FileServiceImpl) Store(filenamestring,reader io.Reader)error{//业务逻辑代码}//创建一个对象tt := FileServiceImpl{}

    • 接口

    接口定义,使用 type *** interface

    typeFileServiceinterface{Store(filenamestring, reader io.Reader) errorLoad(filenamestring, writer io.Writer) error}

    接口实现

    type FileServiceImplstruct{}func (f FileServiceImpl) Store(filenamestring,reader io.Reader)error{err := utils.MongoFileSave(filename, reader)returnerr}func (f FileServiceImpl) Load(filenamestring,writer io.Writer)error{err := utils.MongoFileRead(filename, writer)returnerr}

    需要注意的是,确保实现类的函数名称和参数与接口定义的名称和参数一致(相同签名)

    • 接口赋值与类型

    空接口的类型是interface{} ,go1.18 之后增加了 any 关键字,和interface{}一样。

    variinterface{}i =new(FileServiceImpl)

    • 接口类型断言

    v, ok := i.(T)//i.(T) 的意思是判断变量 i 是否为 T 的类型。//是的话ok 返回ture ,并且v为该类型的变量

    这要求 i 的类型必须是接口,否则会报错:Invalid type assertion: intValue.(int64) (non-interface type int64 on left)

    例如:

    varintValint64=123456variinterface{} = intVal//类型匹配,v 是值,ok 是 booleanv,ok := i.(int64)fmt.Printf("v = %d, ok= %t, type of v: %Tn", v, ok, v)//如果不是这个类型,v2v2, ok := i.(string)fmt.Printf("v2 = %d, ok= %t, type of v2: %Tn", v2, ok, v2)v3 := i.(int64)fmt.Printf("v3 = %d, type of v3: %Tn", v3, v3)//类型不对,会直接 panic 报错v4 := i.([]int)fmt.Printf("v4 = %d, type of v4: %Tn", v4, v4)

    4.7 异常

    golang 并没有类似java一样的try{}catch(){}finally{}进行异常捕获。因为 golang 的设计者认为try catch会消耗更多资源,而且不管从try里面哪个地方跳出来,都是对代码正常结构的一种破坏。

    在go语言中可以使用panic来抛出异常,使用recover方法来处理异常,通常recover方法写在每个方法defer模块中。

    大部分情况下,我们可以用这种方式来处理错误信息

    funcDemo()(int, error){if...... {return0, errors.New("哦哦,出错啦!");}return1,nil}

    或者通过panic、recover处理

    defer 是一个确保在函数返回前执行的过程。

    funcDemo()(int, error){deferfunc(){i :=recover()e, ok := i.(error)ifok {ife.code ==1{fmt.Println(e.message)}}}()panic(error{1,"Fault"})}

    具体的异常处理方式,我们在另一个关于error 和 panic 的文章来特别讨论。

    4.8 管道channel

    channel 是golang 语言中非常有特色且优秀的设计。常常用在异步、队列等场景。使用方式如下:

    funcmain(){// 声明一个管道varchchanint// 初始化管道ch =make(chanint,10)// 向管道中增加10个值fori :=0; i <10; i++ {ch <- i}// 管道消费for{// c是接受对象,ok是本次读取的装填// 当管道中没有值了或管道关闭了,这时就会返回falsec, ok := <-chifok {fmt.Println(c)}else{break}}// 关闭管道close(ch)}

    以异步队列方式执行例子如下:

    varwaitGroup = sync.WaitGroup{}varch_quit = make(chan bool,10)var ch = make(chan int,10)//初始化func init(){// 管道消费for{// c是接受对象,ok是本次读取的装填// 当管道中没有值了或管道关闭了,这时就会返回falsec, ok := <-chif ok {fmt.Println(c)}else{break}}ch_quit<-true}func main() {// 声明一个管道// 向管道中增加10个值fori :=0;i<10; i++ {ch<- i}<-ch_quit}

05

一个简易的Web开发

利用go的net包的http.ListenAndServe实现一个简单的web服务

packagemainimport("fmt""net/http""strings""log")funcsayhello(w http.ResponseWriter, r *http.Request){r.ParseForm()//解析参数,默认是不会解析的fmt.Println(r.Form)//这些信息是输出到服务器端的打印信息fmt.Println("path", r.URL.Path)fmt.Println("scheme", r.URL.Scheme)fmt.Println(r.Form["url_long"])fork, v :=ranger.Form {fmt.Println("key:", k)fmt.Println("val:", strings.Join(v,""))}fmt.Fprintf(w,"Hello Wrold!")//输出到客户端}funcmain(){http.HandleFunc("/", sayhello)//设置访问的路由err := http.ListenAndServe(":9090",nil)//设置监听的端口iferr !=nil{log.Fatal("ListenAndServe: ", err)}}

利用go的net包的http.Server实现一个简单的web服务

import("fmt""io""log""net/http")varmuxmap[string]func(http.ResponseWriter, *http.Request)funcdoRequest(w http.ResponseWriter, r *http.Request){r.ParseForm()//解析url传递的参数,对于POST则解析响应包的主体(request body)fmt.Fprintf(w,"service start...")//这个写入到w的是输出到客户端的 也可以用下面的 io.WriteString对象}typedoHandlerstruct{}func(*doHandler)ServeHTTP(w http.ResponseWriter, r *http.Request){ifres, ok := mux[r.URL.String()]; ok {res(w, r)return}io.WriteString(w,"url params: "+r.URL.String())}funcmain(){server := http.Server{Addr:":9090",Handler: &doHandler{},}mux =make(map[string]func(http.ResponseWriter, *http.Request))mux["/test"] =doRequesterr:=server.ListenAndServe()iferr!=nil{log.Fatal("ListenAndServe: ", err)}}

06

总结

是不是感觉Golang的开发入门比较快,因为Go是Google设计的,研发团d队汇聚了一堆骨灰级的语言开发之父,Golang语言也吸取了java、C++、Python等优秀语言的长处,因此,只要有其他开发语言的经验,学习golang易如反掌。

这也是我们喜欢Go的原因之一。

原创文章 半小时Golang开发入门,版权所有
如若转载,请注明出处:https://www.itxiaozhan.cn/202210460.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注