```go
func (f *FlagSet) String(name string, value string, usage string) *string {
p := new(string)
f.StringVar(p, name, value, usage)
return p
}```
这个是flag源码中的,我们见过new一个chan,或是new一个slice,但是new一个string还是第一个见。
1. string 本身也是一个结构体,所以,new(string) 本身是没有问题的.
```
// src/runtime/string.go:stringStruct
type stringStruct struct {
str unsafe.Pointer
len int
}
```
可以看下这篇文章:https://rainbowmango.gitbook.io/go/chapter01/1.6-string
2. 至于 flag 包下为什么要这样设计?你可以接着往下看下源码,
```golang
type Value interface {
String() string
Set(string) error
}
func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
// f,Var 会生成一个 *Flag{},其中有一个属性是一个 叫Value 的interface,
// 而newStringValue出来的*stringValue实现了叫Value 的interface
f.Var(newStringValue(value, p), name, usage)
}
// -- string Value stringValue 底层其实就是String,通过这种方法,我们可以给stringValue添加额外的方法,就相当于变相给 string,添加了额外的方法
type stringValue string
func newStringValue(val string, p *string) *stringValue {
*p = val
return (*stringValue)(p)
}
func (s *stringValue) Set(val string) error {
*s = stringValue(val)
return nil
}
func (s *stringValue) Get() interface{} { return string(*s) }
func (s *stringValue) String() string { return string(*s) }
```
其他的什么 type uintValue uint ...都是类似的。。。
这样做的好处是以后我们还想加一些其他的类型的时候,只需要加一个别名和实现Value 这个interface,就可以了,这就是做到了所谓的`开闭原则`:对扩展是开放的,但是对于修改是封闭的
#1