Golang 读写文件

ioutil.ReadAll 读取文件

废话不多说, 先看一段读取文件的代码:

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
)

func main() {
	f, err := os.Open("./config.txt")  // 打开文件, 返回一个 *File 指针
	if err != nil {
		log.Fatal(err)
	}

	defer f.Close()

	c, err := ioutil.ReadAll(f)  // 一次读取所有内容
	fmt.Println(string(c))
}

以上代码简单的读取了一个文件的所有内容. 可以从代码中看出, os.Open() 函数打开了了一个文件, 然后我们用 ioutil.ReadAll() 读取该文件内容, 最后用 defer f.close() 关闭该文件(一定要记得关闭文件!!!)

……

阅读全文

Golang 标准库 io/ioutil

io/ioutil 包

软件包 ioutil 实现了一些 I/O 实用程序功能

ReadAll

函数原型:

func ReadAll(r io.Reader) ([]byte, error)

ReadAll 从 r 读取, 直到出现错误或 EOF, 然后返回读取的数据

成功调用将返回 err == nil, 而不是 err == EOF. 因为 ReadAll 被定义为从 src 读取, 直到 EOF, 因此不会将读取的 EOF 视为要报告的错误

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"strings"
)

func main() {
	r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.")

	b, err := ioutil.ReadAll(r)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%s", b)
}
……

阅读全文

Golang 反射

反射

反射是程序在运行时检查其变量和值并找到其类型的能力

首先, 正常时候, 需要查看程序中某个变量的类型和值会这么写:

package main

import (  
	"fmt"
)

func main() {  
	i := 10
	fmt.Printf("%d %T", i, i)
}

这里的变量 i 在编译的时候, 类型就已经是已知的, 所以我们可以打印他的类型

……

阅读全文

Golang 工程管理

工程管理

Go 中有许多工具可以更便捷的进行工程管理, 大致可分为以下几个方面:

  • 代码风格
  • 文档风格和管理
  • 单元测试与性能测试方法
  • 项目工程结构
  • 跨平台开发
  • 打包分发

Go 语言自带的 go 命令工具十分强大, 可以完成以下几类工作:

  • 代码格式化 (go fmt)
  • 代码质量分析和修复
  • 单元测试与性能测试 (go test,
  • 工程构建 (go build)
  • 代码文档的提取和展示 (go doc)
  • 依赖包的管理 (go get)
  • 执行其他的包含指令, 如 6g 等
……

阅读全文

Golang 安全编程

安全编程

数据加密

采用单密钥的加密算法, 称为对称加密. 常见的算法有 DES, AES, RC4 等

采用双密钥的加密算法, 称为非对称加密. 私钥加密的密文, 只有公钥能解密, 反过来也一样. 常见的算法有 RSA 等

在对称加密中, 密钥是不能公开的; 而非对称加密中, 公钥是公开的, 私钥是保密的

某些情况下, 不需要对密文进行解密, 例如哈希算法等. 常见的哈希算法包括 MD5, SHA-1, SHA-256 等

……

阅读全文

Golang 网络编程

Go 语言标准库提供 net 包, 支持基于 IP 层, TCP/UDP 层及更高层面 (如 HTTP, FTP, SMTP) 的网络操作

Socket 编程

传统的 Socket 编程方式大致会有以下几个步骤:

  1. 建立 Socket: 使用 socket() 函数
  2. 绑定 Socket: 使用 bind() 函数
  3. 监听: 使用 listen() 函数, 或者连接: 使用 connect() 函数
  4. 接受连接: 使用 accept() 函数
  5. 接受: 使用 receive() 函数, 或者发送: 使用 send() 函数

而 Go 标准库对对此过程进行了抽象和封装, 无论我们期望使用协议建立什么形式的连接, 都只需要调用 net.Dial() 即可

……

阅读全文

Golang 并发编程

并发编程

并发实现模型有有以下几种主流模型:

  • 多进程: 开销最大, 进程与进程间互不影响
  • 多线程: 比多进程开销小, 高并发下效率有影响
  • 基于回调的非阻塞/异步IO: 高并发服务器上, 多线程会很快耗尽服务器的内存和 CPU 资源. 使用异步 IO, 且尽可能的少用线程, 可以很好的降低开销
  • 协程: 本质上是一种用户态线程, 寄存于线程中, 开销非常小, 不需要操作系统来进行抢占式调度. 缺点是需要编程语言支持, 若语言不支持, 需要用户自行实现调度器

“共享内存系统”: 线程类并发模式中, 线程间通信只能采用共享内存的方式, 为了保证内存的有效性, 我们会给共享内存加锁等来避免资源竞争

“消息传递系统”: 对线程共享状态的各种操作都被封装在线程之间传递的消息中. 由于在发送消息是需要对状态进行复制, 并且在消息传递边界上交出这个状态的所有权. 所以大多数消息传递的实现在性能上并不优越, 但线程中的状态管理工作会变得更为简单

……

阅读全文

Golang 接口

接口

Go 语言中的接口不是其他语言中的接口所提供的接口概念

在 Go 出现之前, 接口主要作为不通组件之间的契约存在, 对契约的实现是强制的, 必须声明你的确是实现了该接口

在 Go 语言中的接口类型是一种抽象的类型. 它不会暴露出它所代表的对象的内部值的结构这个对象支持的基础操作的集合, 它只会展示出他们自己的方法.

也就是说, 当你看到一个接口类型的值时, 你不知道它是什么, 唯一知道的就是可以通过它的方法来做什么

……

阅读全文

Golang 类型系统

类型系统

类型系统是指一个语言的类型体系结构, 是一门编程语言的地基

一个典型的类型系统通常包含如下基本内容:

  • 基础类型, 如 byte, int, bool, floot
  • 复合类型, 如数组, 结构体, 指针
  • 可以指向任意对象的类型(Any 类型)
  • 值语义和引用语义
  • 面向对象, 即所有具备面向对象特征的类型
  • 接口

Go 语言中的大多数类型都是值语义, 并且都可以包含对应的操作方法. 在需要的时候, 你可以给任何类型 (包括内置类型) “增加” 新的方法. 而在实现某个接口时, 无需从该接口继承 (实际上, Go 语言不支持面向对象中的继承语法), 只需要实现该接口要求的所有方法即可

任意类型都可以被 Any类型 引用. Any类型 就是空接口, 即 interface{}

……

阅读全文

Golang 错误处理

错误处理

一. error 接口

Go 引入了一个关于错误处理的标准模式, 即 error 接口, 定义如下:

type error interface {
    Error() string
}

// 对于大多数函数, 如果要返回错误, 大致上可以定义为如下模式, 将 error 作为多返回结果的最后一个
func Foo(param int) (n int, err error) {
    ...
}

// 调用时错误处理格式
n, err := Foo(0)

if err != nil {
    // 错误处理
} else {
    // 使用返回值n
}
……

阅读全文