GO语言简介与基本语法概述

本文的目标

本文通过对Go基本语法进行简要概述,旨在通过短时间内的学习即可掌握基本的Go语法,并切实参与到实际Go项目的开发中。

Go语言简介

Go语言由来自Google公司的Robert Griesemer,Rob Pike和Ken Thompson于2007年9月开始设计和实现,然后于2009年的11月对外正式发布,被誉为“21世纪的C语言”。GO语言相较于Java语言有着更强的时代特点,具体表现为在网络服务应用开发中Go语言的内置库可以帮我们极大地简化相关操作,如下所示:

package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", handler) 
    log.Fatal(http.ListenAndServe("localhost:8000", nil))
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
}

可以看到,我们只用了不到十行的代码即实现了一个简单的web服务。在Go中,每一次请求都以“Handler”的形式存在着,/开头的请求其实就是所有发送到当前站点上的请求,服务监听8000端口。发送到这个服务的“请求”是一个http.Request类型的对象,这个对象中包含了请求中的一系列相关字段,其中就包括我们需要的URL。当请求到达服务器时,这个请求会被传给handler函数来处理,这个函数会将/hello这个路径从请求的URL中解析出来,然后把其发送到响应中。

上面的例子很鲜明地介绍了Go语言在web应用开发中的优势,而如果想使用Java达成同样的效果需要Tomcat组件的支持。但Go语言开发的便携性还不止这些,实际上Go在自动垃圾回收、一个包系统、函数作为一等公民、词法作用域、系统调用接口等方面都有比较出色的表现,简洁的语法、语言本身的向后兼容性和开放的开发生态都是Go语言的优势所在,这也使得Go语言在各个方面都逐渐取代其他的开发语言。

接下来注重通过例子介绍基本的语法,完成最基本的上手。

Go基本语法

基本输入输出

//case 1
package main

import "fmt"

func main() {
    var input1 string  
    fmt.Scanln(&input1)  
    fmt.Println("hello,世界")  
    fmt.Println(input1)
}

上述的代码分为3块结构:

①package:Go语言的代码通过包(package)组织,包类似于其它语言里的库(libraries)或者模块(modules)。一个包由位于单个目录下的一个或多个.go源代码文件组成,目录定义包的作用。每个源文件都以一条package声明语句开始,这个例Go语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循一个简单的命名规则:一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线。大写字母和小写字母是不同的:heapSort和Heapsort是两个不同的名字。系,通过这条语句可以导入其他的包

③func main:main函数,程序的入口,和本处的package main对应(main包定义了一个独立可执行的程序)

上述程序展示了最基本的输入输出,通过调用fmt的Scanln函数将键盘输入的字符赋值给string类型的变量,Println函数又输出了相应的字符串,完成了一个基本的输入输出程序。

命名规则

Go语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循一个简单的命名规则:一个名字必须以一个字母或下划线开头,后面可以跟任意数量的字母、数字或下划线,同时区分大小写,这与C的命名规则非常相似。同时Go语言内也存在25个关键字,这些关键字只能在特定语法环境下使用,现罗列如下:

break      default       func     interface   select
case       defer         go       map         struct
chan       else          goto     package     switch
const      fallthrough   if       range       type
continue   for           import   return      var

此外,还有多个预定义的名字,也不可用于命名

true      false      iota       nil      int     
int8      int16      int32      int64    uint 
uint8     uint16     uint32     uint64   uintptr
float32   float64    complex128 complex64
bool      byte       rune       string   error
make      len        cap        new      append 
copy      close      delete     complex  real 
imag      panic      recover

在习惯上,Go语言程序员推荐使用 驼峰式 命名。

声明

声明语句定义了程序的各种实体对象以及部分或全部的属性。Go语言主要有varfuncconsttype这四种声明,分别对应变量、函数、常量和类型。下面的范例给出了这四种声明的具体表现形式

package main  
  
import "fmt"  
  
// People type可创建struct和interface  
type People struct{  
year int  
weight float64  
height float64  
}  
  
// ConstInt const用于创建常量,常量在创建后值无法再被修改  
// 同时在指定常量时可以不指定类型,golang可自行转换  
const ConstInt = 123  
  
// MaxNum func创建函数  
func MaxNum(a int64, b int64) int64 {  
if a > b {  
return a  
} else {  
return b  
}  
}  
  
func main() {  
var f = ConstInt  
var c = (f - 32) * 5 / 9  
fmt.Println(c, f)  
}

数据类型

在 Go 编程语言中,数据类型用于声明函数和变量,具体分类如下:

类型详解
布尔型布尔型的值只可以是常量 true 或者 false。
数字类型整型 int 和浮点型 float。Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。
字符串类型字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
派生类型(a) 指针类型(Pointer)(b) 数组类型© 结构化类型(struct)(d) Channel 类型(e) 函数类型(f) 切片类型(g) 接口类型(interface)(h) Map 类型

变量作用域

在Go中变量根据作用域可划分为3类:全局变量,局部变量,形式参数

  • 函数内定义的变量为局部变量,这种局部变量的作用域只在函数体内,函数的参数和返回值变量都属于局部变量。这种变量在存在于函数被调用时,销毁于函数调用结束后。
  • 函数外定义的变量为全局变量,全局变量只需要在一个源文件中定义,就可以在所有源文件中使用,甚至可以使用import引入外部包来使用。全局变量声明必须以 var 关键字开头,如果想要在外部包中使用全局变量的首字母必须大写
  • 函数定义中的变量成为形式参数,定义函数时函数名后面括号中的变量叫做形式参数(简称形参)。形式参数只在函数调用时才会生效,函数调用结束后就会被销毁,在函数未被调用时,函数的形参并不占用实际的存储单元,也没有实际值。形式参数会作为函数的局部变量来使用

数组与切片

数组是个不陌生的概念,它是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。数组的呈现形式往往是一个定长的序列。我们可根据数组的下标来访问并修改指定位置的元素,其中索引的范围是从0开始到数组长度减1的位置,内置的len函数将返回数组中元素的个数。

package main  
  
import "fmt"  
  
func main() {  
var a [3]int  
a[1] = 3  
fmt.Println(a[1])  
fmt.Println(a[0], a[len(a)-1])  
}

默认情况下,数组的每个元素都被初始化为元素类型对应的零值,对于数字类型来说就是0。我们也可以使用数组字面值语法用一组值来初始化数组。在数组字面值中,如果在数组的长度位置出现的是“...”省略号,则表示数组的长度是根据初始化值的个数来计算。对数组元素的遍历与迭代,我们可以采用range方法。

package main  
  
import "fmt"  
  
func main() {  
var q [3]int = [...]int{1, 2, 3}  
var r [3]int = [3]int{1, 2}  
fmt.Println(r[1], q[2])  
for _, b := range q {  
fmt.Println(b)  
}  
}

数组作为一种定长结构在使用上略有不便。在实际开发中我们会使用Go语言中数组的一种衍生结构:Slice(切片)。Slice(切片)代表变长的序列,序列中每个元素都有相同的类型。一个slice类型一般写作[]T,其中T代表slice中元素的类型;slice的语法和数组很像,只是没有固定长度而已。Go语言中切片的内部结构包含地址、大小和容量,切片一般用于快速地操作一块数据集合,如果将数据集合比作切糕的话,切片就是你要的“那一块”,切的过程包含从哪里开始(切片的起始位置)及切多大(切片的大小),容量可以理解为装切片的口袋大小。切片操作可以选定任意范围内的元素,给我们的开发带来了便利。

package main  
  
import "fmt"  
  
func main() {  
var q = [...]int{1, 2, 3}  
var r = [...]int{1, 2, 3, 4, 5}  
//从第一位(0)一直遍历到最后一位  
fmt.Println(q[0:])  
//遍历下标[1,3)的元素  
fmt.Println(r[1:3])  
}

Slice作为一种变长结构,通过append方法可以动态扩充slice的长度

package main  
  
import "fmt"  
  
func main() {  
var slice []int  
slice = append(slice, 1) // 在末尾添加元素  
slice = append(slice, 2)  
slice = append(slice, 3)  
slice = append([]int{0}, slice...) // 在开头位置添加1个元素  
slice = append([]int{-3, -2, -1}, slice...) // 在开头添加1个切片  
fmt.Println(slice[0:])  
}

Map(哈希表)

Go语言中的map(映射、字典)是一种内置的数据结构,它是一个无序的key/value对的集合,其中所有的key都是不同的,通过给定的key可以在常数时间复杂度内检索、更新或删除对应的value。Go语言中并没有提供一个set类型,但是map中的key也是不相同的,可以用map实现类似set的功能。Go语言的map采用的数据结构: 哈希表(hash table)。在很多场景下哈希表性能很高,哈希查找表最坏的时间复杂度是O(n),平均查找效率是O(1),如果哈希函数设置得合理最坏得情况不会出现。我们可以通过内置的make函数创建一个map,对map的赋值、元素插入也相当方便:

package main  
  
import "fmt"  
  
func main() {  
ages := make(map[string]int)  
ages["start"] = 1  
ages["end"] = 2  
fmt.Println(ages["start"], ages["end"])  
}

删除操作需要调用delete方法,指定key值即可完成删除

delete(ages, "start")  
fmt.Println(ages["start"])

结构体

结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体。结构体的出现给数据的操作带来了极大的灵活性,每个值称为结构体的成员。如果结构体没有任何成员的话就是空结构体,写作struct{}。它的大小为0,也不包含任何信息,但是有时候依然是有价值的。

package main  
  
import "fmt"  
  
type People struct {  
name string  
year int  
weight float64  
height float64  
}  
  
func main() {  
var a People  
a.weight = 11  
a.height = 12  
a.year = 0  
a.name = "张三"  
var b = People{name: "李四", year: 12, weight: 120, height: 140}  
fmt.Println(a, b)  
}

常用语句

语句描述
if 语句if 语句 由一个布尔表达式后紧跟一个或多个语句组成。
if…else 语句if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。
switch 语句switch 语句用于基于不同条件执行不同动作。
package main  
  
import (  
"fmt"  
"math/rand"  
)  
  
func main() {  
var a = rand.Uint32() % 100  
if a >= 10 {  
fmt.Println("a = ", a, "a不是个位数")  
} else {  
fmt.Println("a = ", a, "a是个位数")  
}  
switch a {  
case 1:  
fmt.Println("a = 1")  
case 2:  
fmt.Println("a = 2")  
}  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值