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接口的类型(导出的类型):
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:
接下来的示例中,我们通过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() {
// ....
} 这个其实也算常识了,写过些代码的人可能都知道。但是在实际的代码中,我们往往还会发现类似这样的一些不好的写法。因此,对于这些惯用法(或者升级为代码规范),我觉得更重要的不是了解知道,而是执行和遵守。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
