go(一)基础知识
一、第一个程序
基本程序结构
package main // 包 import "fmt" // 引入依赖代码
// 功能实现
func main() {
fmt.Println("hello world!")
}
注意点:
1.应用程序入口
- 必须是main包:package main
- 必须是main方法:func main()
- 文件名不一定是main.go
2.退出返回值
与其他主要编程语言的差异
- Go中main函数不支持任何返回值
- 通过os.Exit来返回状态
3.获取命令行参数
main函数不支持传入参数
func main()
在程序中直接通过os.Args获取命令行参数
编写测试文件
源码文件以_test结尾:xxx_test.go
测试方法名以Test开头:func TestXXX(t *testing.T){...}
package try_test
import "testing"
func TestFirstTry(t *testing.T) {
t.Log("My first try!")
}
结果
=== RUN TestFirstTry
--- PASS: TestFirstTry (.00s)
first_test.go:: My first try!
PASS
Fibonacci数列
package try import (
"fmt"
"testing"
) func TestFibList(t *testing.T) {
var a int =
var b int = //var{
// 可以省略int,类型推断
// a int = 1
// b int = 1
//}
// 类型推断,初试化
//a := 1
//b := 1
fmt.Print(a, " ")
for i:=;i<;i++{
fmt.Print(" ", b)
tmp:=a
a=b
b=tmp+a
}
fmt.Println()
}
二、变量、常量、数据类型和运算符
变量赋值
与其他主要编程语言的差异
赋值可以进行自动推断
在一个赋值语句中可以对多个变量进行同时赋值
func TestExchage(t *testing.T){
a :=
b :=
//tmp := a
//a = b
//b = tmp
a, b= b, a
t.Log(a, b)
}
常量定义
与其他主要编程语言的差异
快速设置连续值
const (
Monday = iota +
Tuesday
Wednesday
Thrusday
Friday
Saturday
Sunday
) const (
Open = << iota
Close
Pending
)
例子
package _const import "testing" const (
Monday = iota +
Tuesday
Wednesday
) const(
Readable = <<iota
Writable
Executable
) func TestConstantTry(t *testing.T) {
t.Log(Monday, Tuesday, Wednesday)
} // 1,2,3 func TestConstantTry1(t *testing.T) {
a := //
t.Log(a&Readable==Readable, a&Writable==Writable, a&Executable==Executable)
} // true,true,true
数据类型
基本数据类型

类型转化
与其他主要编程语言的差异
1.Go语言不允许隐式类型转换
2.别名和原有类型也不能进行隐式类型转换
package type_test
import "testing"
type MyInt int64
func TestImplict(t *testing.T) {
var a int =
var b int64
//b = a // 不支持隐式类型转换
b = int64(a)
t.Log(a, b)
var c MyInt
// c = b // 别名的隐式类型转换也不支持
c = MyInt(b)
t.Log(a, b, c)
}
类型的预定义值

指针类型
与其他主要编程语言的差异
1.不支持指针运算
func TestPoint(t *testing.T) {
a :=
aPtr := &a
t.Log(a, aPtr)
t.Logf("%T %T", a, aPtr)
//aPtr = aPtr + 1 // 出错,不支持指针运算
}
结果
=== RUN TestPoint
--- PASS: TestPoint (0.00s)
type_test.go:22: 1 0xc04205e290
type_test.go:23: int *int
PASS
2.string是值类型,其默认初试化值为空字符串,而不是nil
func TestString(t *testing.T) {
var s string
t.Log("*"+s+"*")
t.Log(len(s))
}
结果
=== RUN TestString
--- PASS: TestString (.00s)
type_test.go:: **
type_test.go::
PASS
运算符
算术运算符

比较运算符

用==比较数组
- 相同维数且含有相同个数元素的数组才可以比较
- 每个元素都相同的才相等
逻辑运算符

位运算符

与其他主要编程语言的差异

三、编写结构化程序
for循环
和其他主要编程语言的差异

示例

实例
func TestWhileLoop(t *testing.T) {
n :=
for n < {
t.Log(n)
n++
}
}
结果
=== RUN TestWhileLoop
--- PASS: TestWhileLoop (.00s)
type_test.go::
type_test.go::
type_test.go::
type_test.go::
type_test.go::
PASS
if条件

与其他编程语言的差异
- condition表达式结果必须为布尔值
- 支持变量赋值
if var declaration; condition {
// code to be executed if condition is true
}
func TestIfMultiSec(t *testing.T) {
if a := == ;a {
t.Log("1==1")
}
}
// a是true,所以执行括号里内容
结果
=== RUN TestIfMultiSec
--- PASS: TestIfMultiSec (.00s)
type_test.go:: ==
PASS
switch条件

与其他主要编程语言的差异
- 条件表达式不限制为常量或整数
- 单个case中,可以出现多个结果选项,使用逗号分隔
- 与C等规则相反,Go语言不需要用break来明确退出一个case
- 可以不设定switch之后的条件表达式,在此情况下,整个switch结构与多个if...else...的逻辑作用等同
可以有多个选项
func TestSwitchMultiCase(t *testing.T) {
for i := ; i < ; i++{
switch i {
case , :
t.Log("Even")
case ,:
t.Log("Odd")
default:
t.Log("It is not 0-3")
}
}
}
相当于if...else...使用
func TestSwitchCaseCondition(t *testing.T) {
for i := ; i < ; i++ {
switch {
case i% == :
t.Log("Even")
case i% == :
t.Log("Odd")
default:
t.Log("unknow")
}
}
}
四、数组和切片
数组的声明

数组元素遍历
与其他主要编程语言的差异

数组截取

切片内部结构

切片声明

切片共享存储结构

数组vs切片
- 容量是否可伸缩
- 是否可以进行比较
五、Map
Map声明

Map元素访问
与其他主要编程语言的差异

Map遍历
Map与工厂模式
- Map的value可以是一个方法
- 与Go的Dock type接口方式一起,可以方便实现单一方法对象的工厂模式
实现Set

六、字符串
与其他主要编程语言的差异

Unicode UTF8

编码与存储

常用字符串函数

package main import (
"fmt"
"strings"
) func main() {
var s string = "hello go"
//判断字符串s是否包含子串
r := strings.Contains(s, "go")
fmt.Println(r) //true var s1 []string = []string{"", "", "", ""}
//将一系列字符串连接为一个字符串,之间用sep来分隔
s2 := strings.Join(s1, ",")
fmt.Println(s2) //1,2,3,4 //子串sep在字符串s中第一次出现的位置,不存在则返回-1
n1 := strings.Index(s, "go")
fmt.Println(n1) //6 //返回count个s串联的字符串
s3 := strings.Repeat(s, )
fmt.Println(s3) //hello gohello go //返回将s中前n个不重叠old子串都替换为new的新字符串,如果n<0会替换所有old子串
s4 := strings.Replace(s, "o", "e", -)
fmt.Println(s4) //helle ge //字符串切割,如果后一个参数为空,则按字符切割,返回字符串切片
s5 := strings.Split(s, " ")
fmt.Println(s5) //[hello go] //切除字符串两端的某类字符串
s6 := strings.Trim(s, "o")
fmt.Println(s6) //hello g //去除字符串的空格符,并且按照空格分割返回slice
s7 := " hello go "
s8 := strings.Fields(s7)
fmt.Println(s8) //[hello go]
}
七、文件读写
文件读写
创建文件 Ceate :文件不存在创建,文件存在,将文件内容清空
参数:name,打开文件的路径,可以是绝对路径和相对路径
func main() {
file, err := os.Create("./hello.txt")
if err != nil {
fmt.Println("Create error:", err)
return
}
defer file.Close()
fmt.Println("succes!")
}
打开文件 Open :以只读方式打开文件,文件不存在也会打开失败
参数:name,打开文件的路径,可以是绝对路径和相对路径
package main import (
"fmt";
"os"
) func main() { file, err := os.Open("./hello.txt")
if err != nil {
fmt.Println("Open error:", err)
return
}
defer file.Close() _, err = file.WriteString("hello")
if err != nil {
fmt.Println("Write error:", err)
return
} fmt.Println("succes!") }
结果
Write error: write ./hello.txt: Access is denied.
打开文件 OpenFile:以只读、只写、读写方式打开文件
参数1:name,打开文件的路径,可以是绝对路径和相对路径
参数2:打开文件权限,O_RDONLY、O_WRONLY、O_RDWR
参数3:一般传6
const (
O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
O_RDWR int = syscall.O_RDWR // 读写模式打开文件
O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
O_CREATE int = syscall.O_CREAT // 如果不存在将创建一个新文件
O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必须不存在
O_SYNC int = syscall.O_SYNC // 打开文件用于同步I/O
O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
)
package main import (
"fmt";
"os"
) func main() { file, err := os.OpenFile("./hello.txt", os.O_RDWR, )
if err != nil {
fmt.Println("OpenFile error:", err)
return
}
defer file.Close() _, err = file.WriteString("hello")
if err != nil {
fmt.Println("Write error:", err)
return
} fmt.Println("succes!") }
结果
succes!
写文件
按字符串写:WriteString(string str)
_, err = file.WriteString("hello")
回车换行 Windows为\r\n Linux为\n
按位置写:
Seek():修改文件的读写指针位置
func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
if err := f.checkValid("seek"); err != nil {
return , err
}
r, e := f.seek(offset, whence)
if e == nil && f.dirinfo != nil && r != {
e = syscall.EISDIR
}
if e != nil {
return , f.wrapErr("seek", e)
}
return r, nil
}
参数1: 偏移量。正是向文件尾偏,负是向文件头偏
参数2:偏移起始位置
io.SeekStart:文件起始的位置 0
io.SeekCurrent:文件当前位置 1
io.SeekEnd:文件结尾位置 2
返回值:表示从文件起始位置到当前文件读写指针位置的偏移量
按字节写:
writeAt():在文件指定偏移位置,写入[]byte,通常搭配Seek()
参数1:带写入的数据
参数2:偏移量
返回值:实际写出的字节数
package main import (
"fmt"
"io"
"os"
) func main() { file, err := os.OpenFile("./hello.txt", os.O_RDWR, )
if err != nil {
fmt.Println("OpenFile error:", err)
return
}
defer file.Close() _, err = file.WriteString("hello")
if err != nil {
fmt.Println("Write error:", err)
return
} off, _ := file.Seek(, io.SeekStart)
fmt.Println(off) // 0 off, _ = file.Seek(, io.SeekCurrent)
fmt.Println(off) // 1 off, _ = file.Seek(, io.SeekEnd)
fmt.Println(off) // 5 off, _ = file.Seek(-, io.SeekEnd)
fmt.Println(off) // 4 off, _ = file.Seek(-, io.SeekEnd)
fmt.Println(off) // 3 n, _ := file.WriteAt([]byte(""), off)
fmt.Println(n) //3 fmt.Println("succes!") }

文件 hello ---> hel111,偏移量3的地方开始写:

读文件
// Reader implements buffering for an io.Reader object.
type Reader struct {
buf []byte
rd io.Reader // reader provided by the client
r, w int // buf read and write positions
err error
lastByte int // last byte read for UnreadByte; -1 means invalid
lastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}
func NewReaderSize(rd io.Reader, size int) *Reader {
// Is it already a Reader?
b, ok := rd.(*Reader)
if ok && len(b.buf) >= size {
return b
}
if size < minReadBufferSize {
size = minReadBufferSize
}
r := new(Reader)
r.reset(make([]byte, size), rd)
return r
}
// NewReader returns a new Reader whose buffer has the default size.
func NewReader(rd io.Reader) *Reader {
return NewReaderSize(rd, defaultBufSize)
}
NewReader 返回的是结构体指针变量
// ReadBytes reads until the first occurrence of delim in the input,
// returning a slice containing the data up to and including the delimiter.
// If ReadBytes encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often io.EOF).
// ReadBytes returns err != nil if and only if the returned data does not end in
// delim.
// For simple uses, a Scanner may be more convenient.
func (b *Reader) ReadBytes(delim byte) ([]byte, error) {
// Use ReadSlice to look for array,
// accumulating full buffers.
var frag []byte
var full [][]byte
var err error
n :=
for {
var e error
frag, e = b.ReadSlice(delim)
if e == nil { // got final fragment
break
}
if e != ErrBufferFull { // unexpected error
err = e
break
} // Make a copy of the buffer.
buf := make([]byte, len(frag))
copy(buf, frag)
full = append(full, buf)
n += len(buf)
} n += len(frag) // Allocate new buffer to hold the full pieces and the fragment.
buf := make([]byte, n)
n =
// Copy full pieces and fragment in.
for i := range full {
n += copy(buf[n:], full[i])
}
copy(buf[n:], frag)
return buf, err
}
按行读:
package main import (
"bufio"
"fmt"
"io"
"os"
) func main() { file, err := os.OpenFile("./hello.txt", os.O_RDWR, )
if err != nil {
fmt.Println("OpenFile error:", err)
return
}
defer file.Close() fmt.Println("succes!") // 创建一个带缓冲区的reader
reader := bufio.NewReader(file) for{
buf, err := reader.ReadBytes('\n') // 读一行
if err != nil && err == io.EOF{
fmt.Println("文件读取完毕")
return
}else if err != nil {
fmt.Println("ReadBytes error:", err)
}
fmt.Print(string(buf))
} }
按字节读、写文件
最常用
read()
write()
大文件拷贝
package main import (
"fmt"
"io"
"os"
) func main() { file_r, err := os.Open("E:/文档/xmind/C#.png")
if err != nil {
fmt.Println("Open err: ", err)
return
}
defer file_r.Close()
// 创建写文件
file_w, err := os.Create("./C#.png")
if err != nil {
fmt.Println("Create err: ", err)
return
}
defer file_w.Close() // 从读文件中读取数据,放到缓冲区中
buf := make([]byte, )
// 循环,从读文件中读取数据,拷贝都写文件中
for {
n, err := file_r.Read(buf)
if err != nil && err == io.EOF {
fmt.Printf("已经读完 n=%d\n", n)
return
}
file_w.Write(buf[: n]) // 读多少,写多少
}
}
结果
已经读完 n=
因此,我们也可以通过n=0来判断文件读取完毕
目录操作
打开目录,和打开目录是一样的
目录中的内容叫目录项
打开目录 OpenFile:以只读、只写、读写方式打开目录
参数1:name,打开文件的路径,可以是绝对路径和相对路径
参数2:打开文件权限,O_RDONLY、O_WRONLY、O_RDWR
参数3:os.ModeDir
返回值:返回一个可以读写目录的文件指针
读目录
func (f *File) Readdir(n int) ([]FileInfo, error) {
if f == nil {
return nil, ErrInvalid
}
return f.readdir(n)
}
参数:n,表示读取目录的成员个数。通常传-1,表示读取目录所有文件对象。
返回值:FileInfo类型的切片。其内部保存了文件名。error中保存错误信息。
// A FileInfo describes a file and is returned by Stat and Lstat.
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() interface{} // underlying data source (can return nil)
}
得到FileInfo类型切片后,可以range遍历切片元素,使用.Name()获取文件名。使用.Size()获取文件大小,使用.IsDir()判断文件是目录还是非目录文件
如,我们可以提示用户提供一个目录位置,打开该目录,查看目录下的所有成员,并判别它们是文件还是目录。
package main import (
"fmt"
"os"
) func main() { // 获取用户输入的目录路径
fmt.Println("请输入待查询的目录:")
var path string
path = "./"
// 打开目录
f, err := os.OpenFile(path, os.O_RDONLY, os.ModeDir)
if err != nil {
fmt.Println("Open dir error: ", err)
}
defer f.Close() // 读取目录项
info, err := f.Readdir(-) for _, fileInfo := range info{
if fileInfo.IsDir(){
fmt.Println(fileInfo.Name(), " 是一个目录")
} else {
fmt.Println(fileInfo.Name(), " 是一个文件c")
}
} }
go(一)基础知识的更多相关文章
- .NET面试题系列[1] - .NET框架基础知识(1)
很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...
- RabbitMQ基础知识
RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...
- Java基础知识(壹)
写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...
- selenium自动化基础知识
什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...
- [SQL] SQL 基础知识梳理(一)- 数据库与 SQL
SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...
- [SQL] SQL 基础知识梳理(二) - 查询基础
SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...
- [SQL] SQL 基础知识梳理(三) - 聚合和排序
SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...
- [SQL] SQL 基础知识梳理(四) - 数据更新
SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...
- [SQL] SQL 基础知识梳理(五) - 复杂查询
SQL 基础知识梳理(五) - 复杂查询 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5939796.html 序 这是<SQL 基础知识梳理( ...
- APP测试入门篇之APP基础知识(001)
前言 最近两月比较多的事情混杂在一起,静不下心来写点东西,月初想发表一遍接口测试的总结,或者APP测试相关的内容,一晃就月底了,总结提炼一时半会也整不完.放几个早年总结内部培训PPT出来 ...
随机推荐
- BZOJ 4238 电压 解题报告
BZOJ 4238 电压 考虑一条边成为答案以后,删去Ta后剩下的图是一个或很多个二分图,即没有奇环 则一条边可以成为答案,当且仅当自己在所有奇环的交上且不在偶环上. 考虑建出dfs树,那么返祖边一定 ...
- Monkey命令及调试
monkey命令: 执行50w次,随机数200,忽略crash,忽略超时,详细信息级别为1:monkey -p 包名 -s 200 --throttle 100 --ignore-crashes -- ...
- [HDU2276]Kiki & Little Kiki 2
题目:Kiki & Little Kiki 2 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2276 分析: 1)如果前一盏灯亮着,则改变这一盏灯 ...
- Nginx (限速)限制并发、限制访问速率、限制流量
Nginx 限制并发访问速率流量,配置还是简单的,看下Nginx文档根据文中这三个模块对照看一下就可以,Nginx限速使用的是漏桶算法(感兴趣可以看下文末的参考资料),需要注意的是:当需要进行限速操作 ...
- HTML版简历
页面预览 在线演示
- upc组队赛16 WTMGB【模拟】
WTMGB 题目链接 题目描述 YellowStar is very happy that the FZU Code Carnival is about to begin except that he ...
- 用select实现多客户端连接
server.c 把accept也看成是一个read类型的函数, 于是我们可以把sockfd也放入到select中 maxi标记当前客户端连接数组的最大下标 select返回值为当前已经准备就绪的fd ...
- js获取下拉框的value值
var Resultstr=""; var param = { action: "MoneyList" };//参数拼接 $.ajax({ type: &quo ...
- Java组合实体模式~
组合实体模式用于EJB持久化机制. 组合实体是表示对象图的EJB实体bean. 当组合实体更新时,内部依赖对象bean将自动更新为由EJB实体bean管理. 以下是组合实体Bean的参与者. 组合实体 ...
- CSS深入理解float
初衷:图片环绕效果 1.会使父元素高度塌陷 2.包裹性 3.让元素block化 4.去空格化 5.清除浮动 .clearfix::after{ content:""; disp ...
