一、第一个程序

基本程序结构

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(一)基础知识的更多相关文章

  1. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  2. RabbitMQ基础知识

    RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...

  3. Java基础知识(壹)

    写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...

  4. selenium自动化基础知识

    什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...

  5. [SQL] SQL 基础知识梳理(一)- 数据库与 SQL

    SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...

  6. [SQL] SQL 基础知识梳理(二) - 查询基础

    SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...

  7. [SQL] SQL 基础知识梳理(三) - 聚合和排序

    SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...

  8. [SQL] SQL 基础知识梳理(四) - 数据更新

    SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...

  9. [SQL] SQL 基础知识梳理(五) - 复杂查询

    SQL 基础知识梳理(五) - 复杂查询 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5939796.html 序 这是<SQL 基础知识梳理( ...

  10. APP测试入门篇之APP基础知识(001)

    前言        最近两月比较多的事情混杂在一起,静不下心来写点东西,月初想发表一遍接口测试的总结,或者APP测试相关的内容,一晃就月底了,总结提炼一时半会也整不完.放几个早年总结内部培训PPT出来 ...

随机推荐

  1. BZOJ 4238 电压 解题报告

    BZOJ 4238 电压 考虑一条边成为答案以后,删去Ta后剩下的图是一个或很多个二分图,即没有奇环 则一条边可以成为答案,当且仅当自己在所有奇环的交上且不在偶环上. 考虑建出dfs树,那么返祖边一定 ...

  2. Monkey命令及调试

    monkey命令: 执行50w次,随机数200,忽略crash,忽略超时,详细信息级别为1:monkey -p 包名 -s 200 --throttle 100 --ignore-crashes -- ...

  3. [HDU2276]Kiki & Little Kiki 2

    题目:Kiki & Little Kiki 2 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2276 分析: 1)如果前一盏灯亮着,则改变这一盏灯 ...

  4. Nginx (限速)限制并发、限制访问速率、限制流量

    Nginx 限制并发访问速率流量,配置还是简单的,看下Nginx文档根据文中这三个模块对照看一下就可以,Nginx限速使用的是漏桶算法(感兴趣可以看下文末的参考资料),需要注意的是:当需要进行限速操作 ...

  5. HTML版简历

    页面预览 在线演示

  6. upc组队赛16 WTMGB【模拟】

    WTMGB 题目链接 题目描述 YellowStar is very happy that the FZU Code Carnival is about to begin except that he ...

  7. 用select实现多客户端连接

    server.c 把accept也看成是一个read类型的函数, 于是我们可以把sockfd也放入到select中 maxi标记当前客户端连接数组的最大下标 select返回值为当前已经准备就绪的fd ...

  8. js获取下拉框的value值

    var Resultstr=""; var param = { action: "MoneyList" };//参数拼接 $.ajax({ type: &quo ...

  9. Java组合实体模式~

    组合实体模式用于EJB持久化机制. 组合实体是表示对象图的EJB实体bean. 当组合实体更新时,内部依赖对象bean将自动更新为由EJB实体bean管理. 以下是组合实体Bean的参与者. 组合实体 ...

  10. CSS深入理解float

    初衷:图片环绕效果 1.会使父元素高度塌陷 2.包裹性 3.让元素block化 4.去空格化   5.清除浮动 .clearfix::after{ content:""; disp ...