加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

golang小程序试验(五)

发布时间:2020-12-16 18:57:40 所属栏目:大数据 来源:网络整理
导读:1. golang的指针 可以将unsafe.Pointer转换成uintptr,然后变相做指针运算 package mainimport "fmt"import "unsafe"type User struct {Id intName string}func main() {u := User{1,"tom"}var up uintptr = uintptr(unsafe.Pointer(u)) + unsafe.Offsetof(u

1. golang的指针

可以将unsafe.Pointer转换成uintptr,然后变相做指针运算

package main

import "fmt"
import "unsafe"

type User struct {
	Id   int
	Name string
}

func main() {
	u := &User{1,"tom"}
	var up uintptr = uintptr(unsafe.Pointer(u)) + unsafe.Offsetof(u.Name)
	var name *string = (*string)(unsafe.Pointer(up))
	fmt.Println(*name)
}

2. package io

实现了io.Reader或io.Writer接口的类型(导出的类型):

  • os.File 同时实现了io.Reader和io.Writer
  • strings.Reader 实现了io.Reader
  • bufio.Reader/Writer 分别实现了io.Reader和io.Writer
  • bytes.Buffer 同时实现了io.Reader和io.Writer
  • bytes.Reader 实现了io.Reader
  • compress/gzip.Reader/Writer 分别实现了io.Reader和io.Writer
  • crypto/cipher.StreamReader/StreamWriter 分别实现了io.Reader和io.Writer
  • crypto/tls.Conn 同时实现了io.Reader和io.Writer
  • encoding/csv.Reader/Writer 分别实现了io.Reader和io.Writer
  • mime/multipart.Part 实现了io.Reader
以上类型中,常用的类型有:os.File、strings.Reader、bufio.Reader/Writer、bytes.Buffer、bytes.Reader

WriteAt()方法简单示例:

file,err := os.Create("writeAt.txt")
if err != nil {
    panic(err)
}
defer file.Close()
file.WriteString("Golang中文社区——这里是多余的")
n,err := file.WriteAt([]byte("Go语言学习园地"),24)
if err != nil {
    panic(err)
}
fmt.Println(n)

file.WriteString("Golang中文社区——这里是多余的")往文件中写入Golang中文社区——这里是多余的;之后file.WriteAt([]byte("Go语言学习园地"),24)在文件流的offset=24处写入Go语言学习园地(会覆盖该位置的内容)。

ReadFrom()方法简单示例:

file,err := os.Open("writeAt.txt")
if err != nil {
    panic(err)
}
defer file.Close()
writer := bufio.NewWriter(os.Stdout)
writer.ReadFrom(file)
writer.Flush()
WriteTo()方法示例:
reader := bytes.NewReader([]byte("Go语言学习园地"))
reader.WriteTo(os.Stdout)
Seek()方法示例:
reader := strings.NewReader("Go语言学习园地")
reader.Seek(-6,os.SEEK_END)
r,_,_ := reader.ReadRune()
fmt.Printf("%cn",r)

在标准库中,有如下类型实现了io.ByteReader或io.ByteWriter:

  • bufio.Reader/Writer 分别实现了io.ByteReader和io.ByteWriter
  • bytes.Buffer 同时实现了io.ByteReader和io.ByteWriter
  • bytes.Reader 实现了io.ByteReader
  • strings.Reader 实现了io.ByteReader

接下来的示例中,我们通过bytes.Buffer来一次读取或写入一个字节(主要代码):

var ch byte
fmt.Scanf("%cn",&ch)

buffer := new(bytes.Buffer)
err := buffer.WriteByte(ch)
if err == nil {
    fmt.Println("写入一个字节成功!准备读取该字节……")
    newCh,_ := buffer.ReadByte()
    fmt.Printf("读取的字节:%cn",newCh)
} else {
    fmt.Println("写入错误")
}
Pipe()方法和PipeReader、PipeWriter结构的示例:
func main() {
    Pipe()
}

func Pipe() {
    pipeReader,pipeWriter := io.Pipe()
    go PipeWrite(pipeWriter)
    go PipeRead(pipeReader)
    time.Sleep(1e7)
}

func PipeWrite(pipeWriter *io.PipeWriter) {
    var (
        i   = 0
        err error
        n int
    )
    data := []byte("Go语言学习园地")
    for _,err = pipeWriter.Write(data); err == nil; n,err = pipeWriter.Write(data) {
        i++
        if i == 3 {
            pipeWriter.CloseWithError(errors.New("输出3次后结束"))
        }
    }
    fmt.Println("close 后输出的字节数:",n," error:",err)
}

func PipeRead(pipeReader *io.PipeReader) {
    var (
        err error
        n   int
    )
    data := make([]byte,1024)
    for n,err = pipeReader.Read(data); err == nil; n,err = pipeReader.Read(data) {
        fmt.Printf("%sn",data[:n])
    }
    fmt.Println("writer 端 closewitherror后:",err)
}
Copy()方法示例:
package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    io.Copy(os.Stdout,strings.NewReader("Go语言学习园地"))
    io.Copy(os.Stdout,os.Stdin)
    fmt.Println("Got EOF -- bye")
}

3. 程序结构

假设有一个服务的大致实现是这样的:

type Service struct {
wg sync.WaitGroup
}
func (p *Service) Start() {
p.wg.Add(1)
go p.run()
}
func (p *Service) Close() {
// ...
p.wg.Wait()
}
func (p *Service) run() {
defer p.wg.Done()
// ....
}
其中run()是服务的主要逻辑实现。这样写法的问题是wg的Add和Done函数调用分离了,容易导致在以后的代码维护中不小心就导致Add和Done的调用不匹配从而Wait执行的结果不符合预期。从代码组织的方式上来说,应该把功能相关的代码尽可能地放在一起。

type Service struct {
wg sync.WaitGroup
}
func (p *Service) Start() {
p.wg.Add(1)
go func() {
p.run()
p.wg.Done()
}()
}
func (p *Service) Close() {
// ...
p.wg.Wait()
}
func (p *Service) run() {
// ....
}
这个其实也算常识了,写过些代码的人可能都知道。但是在实际的代码中,我们往往还会发现类似这样的一些不好的写法。因此,对于这些惯用法(或者升级为代码规范),我觉得更重要的不是了解知道,而是执行和遵守。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读