Golang 基础知识
大家好,我叫谢伟,是一名程序员。
刚刚工作一年,在编程领域是一名小兵。
对于初学者,或者说自学编程的人, 我非常理解他们自学的烦恼在哪里。
因为我也是从自学一路过来的。都会经历这些过程, 坚持下去就行, 相信我, 你幷不孤独.
如果你打算走编程的道路, 第一份工作一定要你喜欢, 或者说不讨厌,同时又是在编程的路上. 坚持下去, 相信我, 你幷不孤独.
怕的是你第一份工作因为诱惑, 走了其他路, 内心又想编程, 这种纠纠结结的状态,会让你过的很不舒服, 焦虑, 难以成长.
我2016年算是正式开始编程。那时小大小闹, 不正规, 怎么好玩怎么来, 学了忘, 忘了学...
我自学编程的时候都是写一些小的示例。没资源,没途径了解在企业里,到底需要些什么样的技能。于是一遍遍熟悉编程语言的特性。相信自学的编程的人大都是这样, 稍微厉害点的,肯琢磨的, 搞几个项目, 可见的项目出来, 就越来越熟练.
我直到毕业后,前大半年都是在学习,慢慢的接触一些东西。知道企业的一般开发流程是怎样的。企业需要什么样的技能,企业需要什么的技术。
我觉得我有必要分享出来一些企业的解决方式:
- 会用些什么
- 开发流程是什么样的
- 需要什么样的人
- 怎么技术选型
...
当然这些受限于我自己的经验,但还是希望对大家有启发.
我的这个专栏,主要是想在自己已经使用 Golang 大半年写了几千行代码、搞过两个完整的项目之后,想更精深 Golang 这门语言的语言特性。
同时我正在看《代码大全》,有必要把一些好的编程思路注意事项分享出来。
这是我写这一系列文章的初衷。
在开始之前, 我再罗嗦两句: 1. 整体统一的代码风格非常重要 2. 刚开始就坚持一些好的编程风格
基础知识
上一节讲了 Golang 环境的搭建、项目的组织和包管理工具 govendor。
插播一个第三方下载包的工具: gopm, 这个工具解决的问题是: go get 一般是从 github 服务器, 或者 google 服务器上下载第三方库, 所以有时候网速慢,或者下载不成功.
地址: gopm
下载 gopm:
go get -u github.com/gpmgo/gopm
再使用 gopm 下载第三方库:
gopm get -g -v ****
这一节讲 Golang 的基础知识。主要包括:
- 变量
- 常量
- 字符串
- 数组
- 切片
- Map
- 结构体
- 函数
- 方法
- 分支
- 循环
这些内容的熟悉就能开始写代码了。
编程和写作类似,这些基础知识就相当于写作中的文字。但为什么不同的人写的代码、文章存在很大的差异,有些人写的好,有些人写的不好。
这其实是代码的组织或者的文字的组织。
初学者往往不太注意这些:
比如:
- 不太注意变量的命名
- 不太注意函数的命名
- 不太注意函数的组织方式
- 不太注意项目的组织(即:代码文件的组织)
- 不太注意整体的布局风格
那他们在注意什么? 注意实现, 一定程度上实现能促进初学者学习的热情. 相信我, 这些不注意,往往到最后会成为你的阻碍.
写代码,最后虽然是计算机执行,但是终归是人的产品,由人来阅读。
除非你对自己的编程水平很有信心,否则这些原则需要坚持。能不抽象就不抽象。做到“望文生义”,即看到你的代码大概就知道你想要干嘛,你的函数想要实现什么样的功能,你的项目想要实现什么样的功能。
这一点,其实之前我也不是太注意。最近不是在阅读《代码大全》嘛。
写一些代码片段可能不太能感受到这些原则能有什么样的益处。一旦你的项目越来越复杂的时候,你别头疼。
1 变量
变量的注意事项有下面几点:
- 命名:
原则:
- 见文知意
- 规范:Golang 中采用驼峰式标准:numberOfClass
- 首字母大写:外部可访问;首字母小写:内部访问
- 长度适中
- 避免使用关键字
var ok bool
var value string
var number int
- 声明及初始化
原则:
- 明确数据类型
- 少使用隐式声明
# Better
var Name string
# No Good
Name := "xieWei"
在函数内部可以使用 :=
初始化,自动判断变量的类型。但是建议使用显式声明
- 使用
原则:
- 变量声明,靠近使用处: 即你需要使用变量就在要使用的地方声明变量,而不是提前声明一大堆,或者远离使用变量的地方,不利于阅读
- 多个变量声明放一起
var (
url string
result []byte
err error
)
url = "http://www.baidu.com"
if result, err = http.Get(url); err!=nil{
// do something
}
常用的布尔值变量名称:
- done
- found
- ok
- success
- flag
使用对仗:
- begin/start
- first/last
- locked/unlocked
- min/max
- next/previous
- old/new
- opened/closed
- visible/invisible
- source/target
- source/destination
- up/down
2 常量
常量注意这几点:
- 关键字:const
const AppName = "App"
3 字符串
- 短的
var Help string
Help = "Thank you for Your help."
- 长的
var HelpMessage string
HelpMessage = `
Hello Everone:
Welcome to here.
Today, we will learn how to learn golang.
`
字符串常用的操作:
库: strings
内置库的使用注意两点:
函数的输入值及类型
函数的输出值及类型
Contains
: 判断是否包含字符串
func Contains(s, substr string) bool
-
Count
: 输出字符串中自字符的个数
func Count(s, sep string) int
-
Index
: 返回字符第一次出现的位置,不存在返回 -1
func Index(s, sep string) int
-
Join
: 按给定的分隔符拼接一个字符串切片成字符串
func Join(a []string, sep string) string
-
LastIndex
: 子串最后一次出现的位置
func LastIndex(s, sep string) int
-
ToLower
: 將字符串全部小寫
func ToLower(s string) string
-
ToUpper
: 將字符串全部大寫
func ToUpper(s string) string
-
Repeat
: 重復字符串
func Repeat(s string, count int ) string
-
Replace
: 替換
func Replace(s, old, new string, n int) string
-
TrimSpace
: 去除字符串前後空格
func TrimSpace(s string) string
-
Split
: 切割
func Split(s, sep string) []string
4 数组
固定長度列表在Golang 里称之为数组.
長度不固定的里称之为切片.
var NumberList = [3]string
NumberList = [3]string{"Python", "Golang", "Java"}
- 获取数组长度:
len
- 获取数组容量:
cap
编程中,凡是可以使用if...else
的都可以使用数组来遍历,再对遍历的值进行操作.
5. 切片
相当于不固定长的数组. 可以初始设置容量, 超过容量后,自动扩充.
- len 获取长度
- cap 获取容量
常用的操作:
- slice
func main(){
var (
value []string
)
value = []string{
"xieWei",
"weiWei",
"wuWei",
}
fmt.Print(value[1:])
}
>>> [weiWei wuWei]
- append
func main(){
var (
value []string
)
value = []string{
"xieWei",
"weiWei",
"wuWei",
}
value = append(value, "shenWei")
fmt.Println(value)
}
>>> [xieWei weiWei wuWei shenWei]
- range 操作
func main(){
var (
value []string
)
value = []string{
"xieWei",
"weiWei",
"wuWei",
}
for index, i:= range value{
fmt.Println(index, i)
}
}
>>>
0 xieWei
1 weiWei
2 wuWei
6. Map
字典: 键值型
- 声明
func mapDeclare(key string, value string)map[string]interface{}{
var (
body map[string]interface{}
)
body = make(map[string]interface{})
body[key] = value
return body
}
func main(){
fmt.Println(mapDeclare("name", "xieWei"))
}
>>> map[name:xieWei]
- 遍历
func main(){
var (
body map[string]interface{}
)
body = make(map[string]interface{})
body["name"] = "xiewei"
body["age"] = 26
body["university"] = "shanghaiUniversity"
rangeMap(body)
}
func rangeMap(body map[string]interface{}) {
for key, value := range body{
fmt.Println(key, value)
}
}
>>>
name xiewei
age 26
university shanghaiUniversity
7. 结构体
结构体在 Golang 里面的作用非常大
- 即是数据类型
- 又可以有方法
作用相当于其他语言的类.
- 声明
type MyExample struct {
Name string
Age int
School string
}
func declare(){
var (
exampleStruct MyExample
)
exampleStruct.Name = "xieWei"
exampleStruct.Age = 26
exampleStruct.School = "shanghaiUniversity"
fmt.Println(exampleStruct)
}
func main(){
declare()
}
>>>
{xieWei 26 shanghaiUniversity}
- 方法:
值传递 一般获取值: func (m MyExample) GetAttrName()string
指针传递一般改变值: func (m *MyExample) SetAttrAge(newAge int)
type MyExample struct {
Name string
Age int
School string
}
func declare() MyExample {
var (
example MyExample
)
example.Name = "xieWei"
example.Age = 26
example.School = "shanghaiUniversity"
fmt.Println(example)
return example
}
func (m MyExample) GetAttrName()string{
return m.Name
}
func (m *MyExample) SetAttrAge(newAge int){
m.Age = newAge
}
func main(){
test := declare()
fmt.Println(test.GetAttrName())
fmt.Println(test)
test.SetAttrAge(18)
fmt.Println(test)
}
>>>
{xieWei 26 shanghaiUniversity}
xieWei
{xieWei 26 shanghaiUniversity}
{xieWei 18 shanghaiUniversity}
- 匿名字段
即隐式的引入一个结构体的所有字段
type MyExample struct {
Name string
Age int
School string
}
type OtherExample struct {
MyExample
}
OtherExample 自动拥有 Name, Age, School 字段
8 函数
函数分为这麽几类:
- 匿名函数
- 结构体的方法
- 普通函数
要写好函数注意下面几点:
- 函数名称: 见文知意
- 参数
- 返回值
- 匿名函数: 即没有名称的函数, 字面意思, 一般用来处理简单的函数
func main(){
var NoNameFunc = func(name string) {fmt.Println(name)}
NoNameFunc("xiewei")
}
- 普通函数
func GetMaxNumber(number float64, other float64) float64 {
return math.Max(number, other)
}
- func 关键字
- GetMaxNumber 函数名称
- number, other 参数 类型 float64
- 返回值类型 float64
9 分支/判断/循环
- if 判断
- if ...else / switch 分支
- for 循环