当前位置: 首页 > news >正文

呼玛网站建设在线资源搜索引擎

呼玛网站建设,在线资源搜索引擎,全国招商加盟网免费,怀化市建设局网站Go-知识-fmt 介绍数值类型字符类型布尔类型其他APIFprintPrintSprintFprintf格式穷举PrintfSprintfFprintlnPrintlnSprintln Appendlnerror自定义 Go-知识-fmt 介绍 fmt 实现了格式化输出,并提供了相应的占位符。 支持的数据类型如下: 数值类型&…

Go-知识-fmt

  • 介绍
  • 数值类型
  • 字符类型
  • 布尔类型
  • 其他
  • API
    • Fprint
    • Print
    • Sprint
    • Fprintf
    • 格式穷举
    • Printf
    • Sprintf
    • Fprintln
    • Println
    • Sprintln
  • Appendln
  • error
  • 自定义

Go-知识-fmt

介绍

fmt 实现了格式化输出,并提供了相应的占位符。

支持的数据类型如下:

  • 数值类型:整数类型,浮点类型
  • 字符类型
  • 指针类型
  • 布尔类型
  • 其他

数值类型

  • %b : 二进制
  • %o : 八进制
  • %x : 十六进制
  • %X : 十六进制
  • %d : 十进制
  • %f : 浮点类型
  • %e : 科学计数法
  • %E : 科学计数法

试一试

func TestFmt(t *testing.T) {number := 100.234numberInt := 45fmt.Printf("整数%%d \t %d\n", numberInt)fmt.Printf("八进制%%o \t %o\n", numberInt)fmt.Printf("十六进制%%x \t %x\n", numberInt)fmt.Printf("十六进制%%X \t %X\n", numberInt)fmt.Printf("布尔值%%b \t %b\n", numberInt)fmt.Printf("浮点值%%f \t %f\n", number)fmt.Printf("科学计数法%%e \t %e\n", number)fmt.Printf("科学计数法%%E \t %E\n", number)
}

执行结果如下

image-20250303200412387

字符类型

  • %s : 字符类型
  • %q : 带双引号

如下代码

func TestFmtString(t *testing.T) {str := "hello world"fmt.Printf("字符类型%%s \t %s\n", str)fmt.Printf("待双引号%%q \t %q\n", str)
}

执行结果如下

image-20250303200717948

布尔类型

  • %t : 布尔类型
func TestFmtBool(t *testing.T) {b := truefmt.Printf("布尔类型%%b \t %t\n", b)
}

image-20250303200907588

其他

  • %T : 判断类型(输出类型)
  • %p : 指针类型
  • %v : 默认格式
  • %#v : 带语法的格式
func TestFmtOther(t *testing.T) {a := 1b := 2.0ok := trueptr := &as := struct {Name string}{Name: "test",}fmt.Printf("类型%%T \t %T\n", a)fmt.Printf("类型%%T \t %T\n", b)fmt.Printf("类型%%T \t %T\n", ok)fmt.Printf("类型%%T \t %T\n", ptr)fmt.Printf("类型%%T \t %T\n", s)fmt.Println()fmt.Printf("指针%%p \t %p\n", ptr)fmt.Printf("指针%%p \t %p\n", &a)fmt.Printf("默认格式%%v \t %v\n", s)fmt.Printf("带语法格式%%#v \t %#v\n", s)
}

image-20250303201340465

API

  • Fprint/Fprintf/Fprintln : 带格式的输出
  • Print/Printf/Println : 标准输出
  • Sprint/Sprintf/Sprintln : 格式化内容为 string

Fprint/Print/Sprint 表示使用默认的格式输出或者格式化内容,Fprintf/Printf/Sprintf表示使用指定的格式输出或格式化内容,Fprintln/Println/Sprintln 表示使用默认的格式输出或格式化内容,同时会在最后加上换行符\n

Fprint

源码如下:

// 
func Fprint(w io.Writer, a ...any) (n int, err error) {p := newPrinter()p.doPrint(a)n, err = w.Write(p.buf)p.free()return
}

newPrinter 干了啥

func newPrinter() *pp {p := ppFree.Get().(*pp)p.panicking = falsep.erroring = falsep.wrapErrs = falsep.fmt.init(&p.buf)return p
}

ppFree 又是个啥

var ppFree = sync.Pool{New: func() any { return new(pp) },
}

ppFree 是一个缓存池

image-20250303214241000

提高对象的利用率

p := ppFree.Get().(*pp)是从缓存池中拿一个 pp 结构,因为缓存池是 any 类型的,所以需要进行类型强转

Pp 结构如下:

type pp struct {buf buffer// arg holds the current item, as an interface{}.arg any// value is used instead of arg for reflect values.value reflect.Value// fmt is used to format basic items such as integers or strings.fmt fmt// reordered records whether the format string used argument reordering.reordered bool// goodArgNum records whether the most recent reordering directive was valid.goodArgNum bool// panicking is set by catchPanic to avoid infinite panic, recover, panic, ... recursion.panicking bool// erroring is set when printing an error string to guard against calling handleMethods.erroring bool// wrapErrs is set when the format string may contain a %w verb.wrapErrs bool// wrappedErrs records the targets of the %w verb.wrappedErrs []int
}

有很多的属性

p.fmt.init(&p.buf)设置pp结构的 fmt 的属性

其中的 fmt 结构

type fmt struct {buf *bufferfmtFlagswid  int // widthprec int // precision// intbuf is large enough to store %b of an int64 with a sign and// avoids padding at the end of the struct on 32 bit architectures.intbuf [68]byte
}type fmtFlags struct {widPresent  boolprecPresent boolminus       boolplus        boolsharp       boolspace       boolzero        bool// For the formats %+v %#v, we set the plusV/sharpV flags// and clear the plus/sharp flags since %+v and %#v are in effect// different, flagless formats set at the top level.plusV  boolsharpV bool
}

对于 pp 结构中 fmt 的初始化

func (f *fmt) clearflags() {f.fmtFlags = fmtFlags{}
}func (f *fmt) init(buf *buffer) {f.buf = buff.clearflags()
}

设置了缓存区,同时清空了标志位。因为 pp 的指针值是缓存的,拿出来的可能是之前用过的,所以需要先初始化清空一下才能使用。

p := newPrinter()之后就是 p.doPrint(a) , 看下 doPrint

func (p *pp) doPrint(a []any) {prevString := falsefor argNum, arg := range a {isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String// Add a space between two non-string arguments.if argNum > 0 && !isString && !prevString {p.buf.writeByte(' ')}p.printArg(arg, 'v')prevString = isString}
}

先判断是不是字符串,如果不是字符串,那么在每个值中间加一个 空格

接着调用 printArg 打印

printArg就是针对go支持的所有格式化占位符,进行替换的一个过程

image-20250303215141010

等待占位符替换完成后,将缓存区内的数据,写入到传入的writer里,n, err = w.Write(p.buf)

最后一步的 p.free() 是把从缓存池中拿出来的对象还回去,并且刷新和释放缓存区

func (p *pp) free() {// Proper usage of a sync.Pool requires each entry to have approximately// the same memory cost. To obtain this property when the stored type// contains a variably-sized buffer, we add a hard limit on the maximum// buffer to place back in the pool. If the buffer is larger than the// limit, we drop the buffer and recycle just the printer.//// See https://golang.org/issue/23199.if cap(p.buf) > 64*1024 {p.buf = nil} else {p.buf = p.buf[:0]}if cap(p.wrappedErrs) > 8 {p.wrappedErrs = nil}p.arg = nilp.value = reflect.Value{}p.wrappedErrs = p.wrappedErrs[:0]ppFree.Put(p)
}

Print

Print 就是调用了 Fprint ,只是传入的writer是标准输出设备

func Print(a ...any) (n int, err error) {return Fprint(os.Stdout, a...)
}

Sprint

SprintFprint 差不多,Sprint不需要将缓存区里面的数据写入到 writer了,直接转为字符串返回即可

func Sprint(a ...any) string {p := newPrinter()p.doPrint(a)s := string(p.buf)p.free()return s
}

Fprintf

Fprintf 相比 Fprint 多了一个入参,也就是格式串。格式串就是带有占位符的字符串

func Fprintf(w io.Writer, format string, a ...any) (n int, err error) {p := newPrinter()p.doPrintf(format, a)n, err = w.Write(p.buf)p.free()return
}

其主要逻辑与 Fprint 相同,区别在于 doPrintf

image-20250304200410022

通过 for i := 0; i < end; 循环逐字符解析格式字符串,分为两个处理阶段:

  • 普通字符:直接写入缓冲区
  • 格式化指令:以 % 开头的部分

image-20250304200526710

遇到 % 后执行以下步骤:

  • 解析标志(#, 0, +, -, )
  • 处理参数索引(如 %[3]d)
  • 解析宽度和精度(支持 * 动态值)
  • 处理特殊动词:
    case ‘w’:
    p.wrappedErrs = append(p.wrappedErrs, argNum)
    case ‘v’:
    // 处理 Go 语法格式

image-20250304201135672

参数处理

  • 使用 argNum 跟踪当前参数索引
  • 调用 printArg 进行实际格式化操作
  • 支持参数重排序(%[n] 语法)

image-20250304201233577

  • 错误包装:处理 %w 时记录错误参数位置
  • 类型反射:通过 reflect.Value 处理不同类型
  • 性能优化:使用 buffer 结构进行高效字符串拼接
  • 语法兼容:支持完整的 printf 语法规范

格式穷举

格式串输出示例说明
%v42通用格式,自动匹配类型
%+v{Name: ""}带字段名的结构体输出
%#v"go"Go语法表示值(带类型信息)
%Tfloat64输出值的类型
%d255十进制整数
%b101二进制表示
%o10八进制表示
%xf小写十六进制
%XF大写十六进制
%cAUnicode字符
%f3.141500默认精度浮点数
%.2f3.14保留2位小数
%e1.234500e+03科学计数法表示
%g1.23456789e+08自动选择最紧凑表示法
%shello原始字符串输出
%q"go"带双引号的字符串
%x676f字符串的十六进制编码
%5d 42右对齐宽度5
%-5d42 左对齐宽度5
%05d00042零填充宽度5
%+d+42显示正负号
% d 42正数前留空格
%[2]d %[1]d2 1参数索引重排序
%*d 42动态宽度(参数指定宽度5)
%.*f3.14动态精度(参数指定精度2)
%p0xc0000160a8指针地址
%werror错误包装(需配合errors包使用)
%v[1 2]切片/数组的默认输出
%#v[]int{1, 2}切片/数组的Go语法表示
%+#10.3f +3.142组合格式:符号+宽度10+精度3
%[3]d %[1]s42 hello多参数混合索引
%+v{X:1 Y:2}结构体带字段名输出
%UU+0041Unicode码点格式
%#b0b101Go语法二进制表示
%#o0o10Go语法八进制表示
%#x0xfGo语法十六进制表示
%sMyInt自定义类型实现String()方法时的输出
%d%!d(string=text)类型不匹配时的错误提示
%d%!d(MISSING)缺少参数时的错误提示

Printf

Printf 很简单直接用标准输出调用 Fprintf

func Printf(format string, a ...any) (n int, err error) {return Fprintf(os.Stdout, format, a...)
}

Sprintf

Sprintf 不需要写入write,直接将缓存区的内容返回即可

func Sprintf(format string, a ...any) string {p := newPrinter()p.doPrintf(format, a)s := string(p.buf)p.free()return s
}

Fprintln

Fprintln 基本上也大差不差的,核心是 doPrintln

func Fprintln(w io.Writer, a ...any) (n int, err error) {p := newPrinter()p.doPrintln(a)n, err = w.Write(p.buf)p.free()return
}

doPrintlndoPrint的基础上,在最后加了换行符\n ,都是使用默认格式打印的

func (p *pp) doPrintln(a []any) {for argNum, arg := range a {if argNum > 0 {p.buf.writeByte(' ')}p.printArg(arg, 'v')}p.buf.writeByte('\n')
}

Println

Println 将标准输出作为 writer 请求 Fprintln

func Println(a ...any) (n int, err error) {return Fprintln(os.Stdout, a...)
}

Sprintln

Sprintln 不需要写入writer 直接将缓冲区的内容返回即可

func Sprintln(a ...any) string {p := newPrinter()p.doPrintln(a)s := string(p.buf)p.free()return s
}

Appendln

追加换行

func TestAppln(t *testing.T) {var s []bytes = fmt.Appendln(s, "hello world")s = fmt.Appendln(s, "hello world")s = fmt.Appendln(s, "hello world")fmt.Print(string(s))
}

image-20250304203750503

error

在格式串中 %w 是错误类型的格式串

除此之外,fmt有针对错误的函数Errorf

image-20250304210059103

doPrintf里面会统计 %w的信息

image-20250304210129623

image-20250304210154743

如果只有一个 %w,那么直接使用 errors.New,如果有多个,需要进行warp处理

errors.New 实际上就是 stringError

image-20250304210248207

warpErrors 就是多个错误

image-20250304210322739

自定义

在java等一些语言中,输出调用自动从 Object继承的ToString方法,将对象信息转为字符串。

在go里面也有类似的接口

image-20250304210451478

Stringer 接口定义的String接口就是默认的结构体转字符串的调用方法

type T struct {Name string
}func (t T) String() string {return fmt.Sprintln(fmt.Sprintf("%q", t.Name))
}func TestString(t *testing.T) {name := T{"hello world"}fmt.Print(name)
}

image-20250304210754399

除此之外,还有一个 接口GoStringer 定义的 GoString 用于适配 %#v 才会调用

image-20250304210921969

type T struct {Name string
}func (t T) String() string {return fmt.Sprintln(fmt.Sprintf("%q", t.Name))
}func (t T) GoString() string {return fmt.Sprintln(fmt.Sprintf("struct T :  %q", t.Name))
}func TestString(t *testing.T) {name := T{"hello world"}fmt.Print(name)fmt.Printf("%#v", name)
}

image-20250304211043872

http://www.cadmedia.cn/news/16085.html

相关文章:

  • 北京建筑设计网站兰州网络推广推广机构
  • 做网站专用图标aso优化技巧大aso技巧
  • 国外视觉设计网站开鲁网站seo站长工具
  • 上海建设牌电动三轮官方网站国际新闻大事
  • 网站建设英文合同点点站长工具
  • javaee是做网站的?深圳网站提升排名
  • 盘锦网站网站建设网络营销产品的首选产品
  • 房产网站定制百度指数移动版
  • 开发一个网站成本世界羽联最新排名
  • 长沙旅游攻略二日游seo咨询常德
  • 正规的丹阳网站建设浙江关键词优化
  • 展示型网站搭建软件外包公司有哪些
  • 可靠的医疗网站建设百度搜索引擎技巧
  • 企业网站形象建设什么是百度竞价
  • 尚海整装为啥口碑那么差盐城网站优化
  • 武汉珞珈网站建设武汉网站推广
  • 北京时代 网站建设群推广
  • 江苏省华建建设股份有限公司网站微信引流推广
  • 怎么用ps做网站前台美工今日重大新闻
  • 企业建立自己网站主要方式网络营销的四大要素
  • 西安建设局网站软件开发培训机构去哪个学校
  • 做网站建设的名声很差吗百度明星搜索量排行榜
  • 廊坊网站建设外包域名推荐
  • 上海浦东医院网站建设正规专业短期培训学校
  • 网站速度诊断超级外链推广
  • b2c商务网站建设郑州网站建设制作公司
  • 雄安免费网站建设南京百度网站快速优化
  • 网站首页建设网站近两年成功的网络营销案例
  • 万商云集(成都)科技股份有限公司万词霸屏百度推广seo
  • wordpress下载站主题重庆人力资源和社会保障网官网