最近一直在GO社区里看大神们写得文章,大神们分享了很多关于GO的学习资料,我很开心可以学习GO语言,我本身是做C#开发的,当然在C#语言领域我也是菜鸟,在接触GO的这段时间,我从一开始的很迷茫,这个东西能做什么呢?真的如网上所说的20世纪的C那么强大么?从GO出现到现在已经四年时间了很多项目已经验证了GO的强大性,国内的七牛云就是一个很好的例子,但是在未来我举得还会有更多的GO语言开发的项目,这可能就是一种大势所趋。
我本人是比较弱的水平,所以和社区的朋友们分享一些自己写的笔记,如果有大神读到的话,还望可以指出其中的不足。当然水平比较高的大牛可以直接跳过。
就像每一门语言的入门一样,我们也从打出第一个Hello word开始学习GO之旅吧。
```go
package main
import "fmt"
func main() {
fmt.Printf("Hello, world or 你好,世界 ")
}
```
GO环境配置和GO的IDE安装我就不讲了,整个社区讲这两点的文章太多,GO语言的简洁性就是如此美丽,package <pkgName>(在我们的例子中是package main)这一行告诉我们当前文件属于哪个包,而包名main则告诉我们它是一个可独立运行的包,它在编译后会产生可执行文件。除了main包之外,其它的包最后都会生成*.a文件(也就是包文件)并放置在$GOPATH/pkg/$GOOS_$GOARCH中,笔者是Windows环境下的GO开发
需要注意的是:每一个可独立运行的Go程序,必定包含一个package main,在这个main包中必定包含一个入口函数main,而这个函数既没有参数,也没有返回值。和C#控制台应用程序很类似,都是必须要有主程序入口。
为了打印Hello, world...,我们调用了一个函数Printf,这个函数来自于fmt包,所以我们在第三行中导入了系统级别的fmt包:import "fmt"。和C#中调用dll是一样的道理,但是GO又将其简化了,可以用
```go
import (
"fmt"
"log"
"net/http"
"strings"
)
```
一次性导入多个系统包,这样看起来是不是就显得很简洁,还不只这些,GO还支持使用别名,加点可以省略使用 fmt.Printf("Hello, world or 你好,世界 ")这种形式,直接使用Printf()来调用函数方法
**GO语言定义变量**
使用var关键字是Go最基本的定义变量方式,与C语言不同的是Go把变量类型放在变量名后面:
`var variableName type`
也可以一次定义多个变量,
`var vname1, vname2, vname3 type`
但是还是没有很简化对吧,其实很多语言都支持这样声明变量,C#中也可以,但是go还有不一样的地方,那就是GO支持:=给变量赋值,这样可以一次性给三个值赋值并且初始化,是不是就非常方便了,不仅仅变量,数组,流程控制语句也都支持这样
```go
/*
定义三个变量,它们分别初始化为相应的值
vname1为v1,vname2为v2,vname3为v3
编译器会根据初始化的值自动推导出相应的类型
*/
vname1, vname2, vname3 := v1, v2, v3
```
现在是不是看上去非常简洁了?:=这个符号直接取代了var和type,这种形式叫做简短声明。不过它有一个限制,那就是它只能用在函数内部;在函数外部使用则会无法编译通过,所以一般用var方式来定义全局变量。
_(下划线)是个特殊的变量名,任何赋予它的值都会被丢弃。在这个例子中,我们将值35赋予b,并同时丢弃34:
`_, b := 34, 35`
Go对于已声明但未使用的变量会在编译阶段报错,比如下面的代码就会产生一个错误:声明了i但未使用。如下,这在C#中是不会的,C#会报出警告,但是不影响你编译,我觉得GO的做法应该是为了让代码看起来更简洁,毕竟声明变量而不用实际上是一种资源浪费
`var i int`
**声明常量**:
所谓常量,也就是在程序编译阶段就确定下来的值,而程序在运行时无法改变该值。在Go程序中,常量可定义为数值、布尔值或字符串等类型。
```go
const constantName = value
//如果需要,也可以明确指定常量的类型:
const Pi float32 = 3.1415926
```
Go 常量和一般程序语言不同的是,可以指定相当多的小数位数(例如200位), 若指定給float32自动缩短为32bit,指定给float64自动缩短为64bit
**内置基础类型**
Boolean
在Go中,布尔值的类型为bool,值是true或false,默认为false。
```go
// 示例代码
var isActive bool // 全局变量声明
var enabled, disabled = true, false // 忽略类型的声明
func test() {
var available bool // 一般声明
valid := false // 简短声明
available = true // 赋值操作
}
```
数值类型
整数类型有无符号和带符号两种。Go同时支持int和uint,这两种类型的长度相同,但具体长度取决于不同编译器的实现。Go里面也有直接定义好位数的类型:rune, int8, int16, int32, int64和byte, uint8, uint16, uint32, uint64。其中rune是int32的别称,byte是uint8的别称。
需要注意的一点是,这些类型的变量之间不允许互相赋值或操作,不然会在编译时引起编译器报错。
如下的代码会产生错误:invalid operation: a + b (mismatched types int8 and int32)
```go
var a int8
var b int32
c := a + b
```
另外,尽管int的长度是32 bit, 但int 与 int32并不可以互用。
浮点数的类型有float32和float64两种(没有float类型),默认是float64。
这就是全部吗?No!Go还支持复数。它的默认类型是complex128(64位实数+64位虚数)。如果需要小一些的,也有complex64(32位实数+32位虚数)。复数的形式为RE + IMi,其中RE是实数部分,IM是虚数部分,而最后的i是虚数单位。下面是一个使用复数的例子:
```go
var c complex64 = 5+5i
//output: (5+5i)
fmt.Printf("Value is: %v", c)
```
字符串
我们在上一节中讲过,Go中的字符串都是采用UTF-8字符集编码。字符串是用一对双引号("")或反引号(` `)括起来定义,它的类型是string。
```go
//示例代码
var frenchHello string // 声明变量为字符串的一般方法
var emptyString string = "" // 声明了一个字符串变量,初始化为空字符串
func test() {
no, yes, maybe := "no", "yes", "maybe" // 简短声明,同时声明多个变量
japaneseHello := "Konichiwa" // 同上
frenchHello = "Bonjour" // 常规赋值
}
```
在Go中字符串是不可变的,例如下面的代码编译时会报错:cannot assign to s[0]
```go
var s string = "hello"
s[0] = 'c'
```
但如果真的想要修改怎么办呢?下面的代码可以实现:
```go
s := "hello"
c := []byte(s) // 将字符串 s 转换为 []byte 类型
c[0] = 'c'
s2 := string(c) // 再转换回 string 类型
fmt.Printf("%s\n", s2)
```
Go中可以使用+操作符来连接两个字符串:
```go
s := "hello,"
m := " world"
a := s + m
fmt.Printf("%s\n", a)
```
修改字符串也可写为:
```go
s := "hello"
s = "c" + s[1:]
// 字符串虽不能更改,但可进行切片操作
fmt.Printf("%s\n", s)
如果要声明一个多行的字符串怎么办?可以通过`来声明:
m := `hello
world`
```
括起的字符串为Raw字符串,即字符串在代码中的形式就是打印时的形式,它没有字符转义,换行也将原样输出。例如本例中会输出:
```
hello
world
```
更多评论