golang文件读写+http基础
一、读取配置文件+rpc
1.information.yaml
id: 2017012229
name: taozui
age: 23
ip: 127.0.0.1
port: 26615
配置文件格式为键值对,注意:后方要有个空格。
2.config.go
package main
import (
"errors"
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
)
type Config struct {
Id int `yaml:"id"`
Name string `yaml:"name"`
Age int `yaml:"age"`
Ip string `yaml:"ip"`
Port string `yaml:"port"`
}
func ReadConfig(fileName string) (*Config, error) {
in, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, err
}
var config Config
err = yaml.Unmarshal(in, &config)
if err != nil {
return nil, err
}
return &config, nil
}
func (c *Config) Verify() error {
if len(c.Ip) == 0 {
return errors.New("Missing IP")
}
if len(c.Port) == 0 {
return errors.New("Missing Port")
}
fmt.Println(c.Ip, ":", c.Port)
return nil
}
准备向与配置文件相对应的结构体(打上yaml标签)存储信息。
ReadConfig方法中先将文件转换为byte流,再使用unmarshal方法将其读入结构体中。
3.server.go
package main
import (
"log"
"net/http"
"net/rpc"
)
type Information int
func (i *Information) GetId(config *Config, reply *string) error {
config.Id--
*reply = "Id--"
return nil
}
func (i *Information) GetAge(config *Config, reply *string) error {
config.Age++
*reply = "Age++"
return nil
}
func (i *Information) GetName(config *Config, reply *string) error {
config.Name = "zhangsan"
*reply = "NameChanged"
return nil
}
func main() {
information := new(Information)
err := rpc.Register(information)
if err != nil {
log.Fatalf("RpcRegisterError, err:%s", err)
}
rpc.HandleHTTP()
err = http.ListenAndServe(":26615", nil)
if err != nil {
log.Fatalf("ServerError:%s", err)
}
}
server.go模仿服务端,提供了服务供客户端远程调用。
rpc库对注册的方法有一定的限制,方法必须满足签名func (t *T) MethodName(argType T1, replyType *T2) error:
首先,方法必须是导出的(名字首字母大写);
其次,方法接受两个参数,必须是导出的或内置类型。第一个参数表示客户端传递过来的请求参数,第二个是需要返回给客户端的响应。第二个参数必须为指针类型(需要修改);
最后,方法必须返回一个error类型的值。返回非nil的值,表示调用出错。
rpc.HandleHTTP()注册 HTTP 路由。http.ListenAndServe(“:26615”, nil)在端口26615上启动一个 HTTP 服务,请求 rpc 方法会交给rpc内部路由处理。
4.main.go
package main
import (
"log"
"net/rpc"
"os"
)
func main() {
//读配置文件
config, err := ReadConfig("information.yaml")
if err != nil {
log.Fatalf("ReadConfigError:%s", err)
}
err = config.Verify()
if err != nil {
log.Fatalf("VerifyError:%s", err)
}
//远程过程调用
clinet, err := rpc.DialHTTP("tcp", config.Ip+":"+config.Port)
if err != nil {
log.Fatalf("DialHttpError:%s", err)
}
service := os.Args[1]
var reply string
err = clinet.Call("Information."+service, config, &reply)
if err != nil {
log.Fatalf("NoResponseError:%s", err)
}
}
客户端使用rpc.DialHTTP(“tcp”, “:26615”)连接到服务端的监听地址,返回一个 rpc 的客户端对象。后续就可以调用该对象的Call()方法调用服务端对象的对应方法,依次传入方法名(需要加上类型限定)、参数、一个指针(用于接收返回值)。
go get gopkg.in/yaml.v3
go run config.go main.go GetId
二、写文件+通过网络下载图片
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"log"
"math/rand"
"net/http"
"os"
"path"
"strconv"
)
func main() {
//简单写
err := ioutil.WriteFile("nohup.out", []byte("reply"), 0666)
if err != nil {
log.Fatalf("WriteFileError:%s", err)
}
//完整写
file, err := os.OpenFile("xxx.txt", os.O_RDWR|os.O_APPEND, 0666)
if err != nil {
file, err = os.Create("xxx.txt")
if err != nil {
log.Fatalf("CreateError:%s", err)
}
}
defer file.Close()
_, err = file.WriteString("aaa ")
if err != nil {
log.Fatalf("WriteStringError:%s", err)
}
//缓冲写
buffer := bufio.NewWriterSize(file, 2048)
buffer.WriteString("get a random number:")
i := rand.Intn(100)
buffer.WriteString(strconv.Itoa(i))
buffer.WriteString("\n")
err = buffer.Flush()
if err != nil {
log.Fatalf("BufferFlushError:%s", err)
}
//下载图片+拷贝写
imgUrl := "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"
fileName := path.Base(imgUrl)
resp, err := http.Get(imgUrl)
if err != nil {
log.Fatalf("HttpGetError:%s", err)
}
defer resp.Body.Close()
reader := bufio.NewReaderSize(resp.Body, 32*1024)
file, err = os.Create(fileName)
if err != nil {
panic(err)
}
writer := bufio.NewWriter(file)
written, _ := io.Copy(writer, reader) //xdg-open filename 显示图片
fmt.Printf("Total length: %d\n", written)
}
简单写:ioutil.WriteFile
完整写:os.OpenFile+os.Write
缓冲写:bufio.NewWriter+bufio.Write
拷贝写:io.Copy
path.Base:截取url最后一段内容
http.Get:http请求,得到响应头和响应体。
go run main.go