Go语言数据类型、输入输出

一、数据类型

Go 语言按类别有以下几种数据类型:

序号类型和描述
1布尔型 布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。
2数字类型 整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。
3字符串类型: 字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
4派生类型: 包括:(a) 指针类型(Pointer)(b) 数组类型(c) 结构化类型(struct)(d) Channel 类型(e) 函数类型(f) 切片类型(g) 接口类型(interface)(h) Map 类型
 GO的数值类型分为以下几种:整数、浮点数、复数,其中每一种都包含了不同大小的数值类型,例如有符号整数包含 int8、int16、int32、int64 等,每种数值类型都决定了对应的大小范围和是否支持正负符号。

Go语言同时提供了有符号和无符号的整数类型,其中包括 int8、int16、int32 和 int64 四种大小截然不同的有符号整数类型,分别对应 8、16、32、64 bit(二进制位)大小的有符号整数,与此对应的是 uint8、uint16、uint32 和 uint64 四种无符号整数类型  

Go语言省去了short,long,double等类型,直接用类似int16,int64这样的方式来表示

关于值传递和引用传递

值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数

引用传递:所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

a、值类型:基本数据类型,int,float,bool,string,以及数组和struct

特点:变量直接存储值,内存通常在栈中分配,栈在函数调用完会被释放

b、引用类型:指针,slice,map,chan等都是引用类型

特点:变量存储的是一个地址,这个地址存储最终的值。内存通常在堆上分配,通过GC回收。

 var x int16=88
        y:=9999999
        z:=3.22
        fmt.Printf("x的类型是%T,值为%v\n",x,x)//格式化输出,使用fmt.Printf()
        fmt.Printf("y的类型是%T,值为%v\n",y,y)
        fmt.Printf("z的类型是%T,值为%v\n",z,z)


//x的类型是int16,值为88
//y的类型是int,值为9999999
//z的类型是float64,值为3.22

类型转换

Go语言中不允许隐式转换,所有类型转换必须显式声明,而且转换只能发生在两种相互兼容的类型之间。

var ch byte = 97
//var a int = ch //err, cannot use ch (type byte) as type int in assignment
var a int = int(ch)

类型别名

type (
    myint int    //int改名为myint
    mystr string //string改名为mystr
)

二、格式化输出

fmt.Printf()格式字符串:

import "fmt"

fmt包实现了类似C语言printf和scanf的格式化I/O。格式化动作('verb')源自C语言但更简单。

fmt.Printf("hi %d",1+9)
//hi 10

Printing

verb:

通用:

%v   值的默认格式表示
%+v     类似%v,但输出结构体时会添加字段名
%#v     值的Go语法表示
%T      值的类型的Go语法表示
%%      百分号

布尔值:

%t   单词true或false

整数:

%b   表示为二进制
%c      该值对应的unicode码值
%d      表示为十进制
%o      表示为八进制
%q      该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示
%x      表示为十六进制,使用a-f
%X      表示为十六进制,使用A-F
%U      表示为Unicode格式:U+1234,等价于"U+%04X"

浮点数与复数的两个组分:

%b   无小数部分、二进制指数的科学计数法,如-123456p-78;参见strconv.FormatFloat
%e      科学计数法,如-1234.456e+78
%E      科学计数法,如-1234.456E+78
%f      有小数部分但无指数部分,如123.456
%F      等价于%f
%g      根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
%G      根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)

字符串和[]byte:

%s   直接输出字符串或者[]byte
%q      该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示
%x      每个字节用两字符十六进制数表示(使用a-f)
%X      每个字节用两字符十六进制数表示(使用A-F)    

指针:

%p   表示为十六进制,并加上前导的0x    

没有%u。整数如果是无符号类型自然输出也是无符号的。类似的,也没有必要指定操作数的尺寸(int8,int64)。

宽度通过一个紧跟在百分号后面的十进制数指定,如果未指定宽度,则表示值时除必需之外不作填充。精度通过(可选的)宽度后跟点号后跟的十进制数指定。如果未指定精度,会使用默认精度;如果点号后没有跟数字,表示精度为0。举例如下:

%f:    默认宽度,默认精度
%9f    宽度9,默认精度
%.2f   默认宽度,精度2
%9.2f  宽度9,精度2
%9.f   宽度9,精度0    

输入输出

本篇涉及函数的知识,不过没有影响

package fmt

fmt包实现了类似C语言printf和scanf的格式化I/O。格式化动作('verb')源自C语言但更简单。

fmt.Println函数我们知道是打印换行的函数。

文档中是这样的:

func Println(a ...interface{}) (n int, err error)

a ...interface{}的意思是接受任意类型的参数, (n int, err error)代表这个函数返回的参数

一、输出

标准输出

常用的标准输出函数有以下三种,都会将数据输出到标准设备,如屏幕。

都是以P开头的函数,用法基本相同。

值得一提的是go语言通过大小写来决定公开程度,如大写字母开头即代表public

 fmt.Println()//输出任意类型数据,并换行
        fmt.Print()  //输出任意类型数据,不换行
        fmt.Printf()//格式化输出数据,不换行

如下:

 fmt.Println("我是fmt.Println()输出的数据,我换行啦")
        fmt.Print("我是fmt.Print()输出的数据,我不换行")
        fmt.Printf("我是  fmt.Printf()输出的数据,格式化输出不换行。。。%s","ha")


我是fmt.Println()输出的数据,我换行啦
我是fmt.Print()输出的数据,我不换行我是       fmt.Printf()输出的数据,格式化输出不换行。。。ha

当然fmt.Print()这些不换行你可以通过转义字符来控制换行,如\n等

非标准输出

也有其他输出,比如Fprintf等,这我们将在后面接触。

Fprintf根据format参数生成格式化的字符串并写入w。返回写入的字节数和遇到的任何错误。

func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)

二、输入

标准输入

 fmt.Scan()//扫描,必须所有参数都被填充后换行才结束扫描
        fmt.Scanln()//扫描,但是遇到换行就结束扫描
        fmt.Scanf()//格式化扫描,换行就结束

??注意以上都是需要使用地址来取得扫描到的数据哈

如fmt.Scan(&x,&y)

分别演示一下

Scan

func main()  {

        var(
                x,y string
        )
        
        fmt.Println("输入两个字符串:")
        fmt.Scan(&x,&y)

        fmt.Println("x :"+x)
        fmt.Println(" y:"+y)

}

结果如下,必须接受两个值才可以结束。输入一个值换行不会结束。

输入两个字符串:
he  

ok
x :he
 y:ok

Scanln

func main()  {
        var(
                x,y string
                z string
        )

        fmt.Println("输入三个字符串:")
        fmt.Scanln(&x,&y,&z)

        fmt.Println("x :"+x)
        fmt.Println(" y:"+y)
        fmt.Println("z:"+z)

}

只要换行就结束

输入三个字符串:
ha yes lala
x :ha
 y:yes
z:lala

//只输入一个字符串也结束
输入三个字符串:
eee
x :eee
 y:
z:

Scanf

func main()  {

        var(
                x,y string
                z string
        )


        fmt.Println("输入三个字符串:")
        fmt.Scanf("%s %s %s",&x,&y,&z)

        fmt.Println("x :"+x)
        fmt.Println(" y:"+y)
        fmt.Println("z:"+z)

}

格式化输入,只要换行就结束

输入三个字符串:
ha la hou 
x :ha
 y:la
z:hou


//只输入一个字符串也结束
输入三个字符串:
eee
x :eee
 y:
z:

非标准输入

如 Fscanf等

func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)

Fscanf从r扫描文本,根据format 参数指定的格式将成功读取的空白分隔的值保存进成功传递给本函数的参数。返回成功扫描的条目个数和遇到的任何错误。

输入输出流

以上标准输入都是fmt包下的,fmt包比较方便

当然也可以通过输入流解决,如下输入:

func main() {
        inputReader := bufio.NewReader(os.Stdin) // 使用了自动类型推导,不需要var关键字声明
        //inputReader = bufio.NewReader(os.Stdin)

        fmt.Println("Please input your name: ")

        //input, err = inputReader.ReadString('\n')
        input, err := inputReader.ReadString('\n')

        if err == nil {
                fmt.Printf("Your name is: %s\n", input)
        }
}

这是输入输出流,在处理复杂数据流的时候很给力,处理简单文本数据就显得比较繁琐了,所以fmt包就是简化版的输入输出,对我们常用的的数据处理进行的封装。