兄弟连区块链培训分享Go语言中获取字符串长度的方法

兄弟连区块链培训 · · 1099 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

  Go语言经过十余年的发展,已成为最流行的新兴语言。目前,Go语言已成为云计算领域的首选语言,且随着近几年区块链的流行,作为底层开发语言的Go再次火爆成为区块链技术培训领域第一编程语言,IBM的Fabic等重量级的区块链项目都是基于Go语言开发的。

  殊不知,Go语言可开发的应用项目还有很多。除云计算、区块链等开源项目外,还包含Devops、人工智能、游戏、存储引擎、Web、系统/命令行工具、中间件、测试/持续交付、文件系统等各方面的开源项目。

一、获取字符串长度的几种方法

-使用 bytes.Count() 统计

-使用 strings.Count() 统计

-将字符串转换为 []rune 后调用 len 函数进行统计

-使用 utf8.RuneCountInString() 统计

例:

str:="HelloWord"


l1:=len([]rune(str))


l2:=bytes.Count([]byte(str),nil)-1)


l3:=strings.Count(str,"")-1


l4:=utf8.RuneCountInString(str)


fmt.Println(l1)


fmt.Println(l2)


fmt.Println(l3)


fmt.Println(l4)


打印结果:都是9


二、strings.Count函数和bytes.Count函数


这两个函数的用法是相同,只是一个作用在字符串上,一个作用在字节上


strings中的Count方法


func Count(s, sep string) int{}

判断字符sep在字符串s中出现的次数,没有找到则返回-1,如果为空字符串("")则返回字符串的长度+1


例:


str:="HelloWorld"


fmt.Println(strings.Count(str,"o"))  //打印 o 出现的次数,打印结果为2


注:在Golang中,如果字符串中出现中文字符不能直接调用 len 函数来统计字符串字符长度,这是因为在 Go 中,字符串是以 UTF-8 为格式进行存储的,在字符串上调用 len 函数,取得的是字符串包含的 byte 的个数。


str:="HelloWorld"


str1 := "Hello,世界"


fmt.Println(len(str1)) //打印结果:13


fmt.Println(len(str)) //打印结果:9 (如果是纯英文字符的字符串,可以使用来判断字符串的长度)


如何跨语言调用golang的RPC方法

上面的三个例子,我们分别使用net/rpc、net/rpc/jsonrpc、protorpc实现了golang中的RPC服务端,并给出了对应的golang客户端RPC调用示例,因为JSON和protobuf是支持多语言的,所以使用jsonrpc和protorpc实现的RPC方法我们是可以在其他语言中进行调用的。下面给出一个php客户端程序,通过socket连接调用jsonrpc实现的服务端RPC方法。


$PHPROOT/jsonrpc.php




class JsonRPC {


    private $conn;


    function __construct($host, $port) {

        $this->conn = fsockopen($host, $port, $errno, $errstr, 3);

        if (!$this->conn) {

            return false;

        }

    }


    public function Call($method, $params) {

        if (!$this->conn) {

            return false;

        }

        $err = fwrite($this->conn, json_encode(array(

                'method' => $method,

                'params' => array($params),

                'id'     => 0,

            ))."\n");

        if ($err === false) {

            return false;

        }

        stream_set_timeout($this->conn, 0, 3000);

        $line = fgets($this->conn);

        if ($line === false) {

            return NULL;

        }

        return json_decode($line,true);

    }

}


$client = new JsonRPC("127.0.0.1", 8096);

$args = array('A'=>9, 'B'=>2);

$r = $client->Call("Arith.Multiply", $args);

printf("%d * %d = %d\n", $args['A'], $args['B'], $r['result']['Pro']);

$r = $client->Call("Arith.Divide", array('A'=>9, 'B'=>2));

printf("%d / %d, Quo is %d, Rem is %d\n", $args['A'], $args['B'], $r['result']['Quo'], $r['result']['Rem']);

其他RPC库

除了上面提到的三种在golang实现RPC的方式外,还有一些其他的rpc库提供了类似的功能,比较出名的有google开源的grpc,但是grpc的初次安装比较麻烦,这里就不做进一步介绍了,有兴趣的可以自己了解。


上面的例子我们演示了使用net/rpc实现RPC的过程,但是没办法在其他语言中调用上面例子实现的RPC方法。所以接下来的例子我们演示一下使用net/rpc/jsonrpc库实现RPC方法,此方式实现的RPC方法支持跨语言调用。


$GOPATH/src/test/rpc/jsonrpc_server.go


package main


import (

    "errors"

    "fmt"

    "log"

    "net"

    "net/rpc"

    "net/rpc/jsonrpc"

    "os"

)


//算数运算结构体

type Arith struct {

}


//算数运算请求结构体

type ArithRequest struct {

    A int

    B int

}


//算数运算响应结构体

type ArithResponse struct {

Pro int //乘积

Quo int //商

Rem int //余数

}


//乘法运算方法

func (this *Arith) Multiply(req ArithRequest, res *ArithResponse) error {

    res.Pro = req.A * req.B

    return nil

}


//除法运算方法

func (this *Arith) Divide(req ArithRequest, res *ArithResponse) error {

    if req.B == 0 {

        return errors.New("divide by zero")

    }

    res.Quo = req.A / req.B

    res.Rem = req.A % req.B

    return nil

}


func main() {

rpc.Register(new(Arith)) //注册rpc服务


    lis, err := net.Listen("tcp", "127.0.0.1:8096")

    if err != nil {

        log.Fatalln("fatal error: ", err)

    }


    fmt.Fprintf(os.Stdout, "%s", "start connection")


    for {

conn, err := lis.Accept() //接收客户端连接请求

        if err != nil {

            continue

        }


go func(conn net.Conn) { //并发处理客户端请求

            fmt.Fprintf(os.Stdout, "%s", "new client in coming\n")

            jsonrpc.ServeConn(conn)

        }(conn)

    }

}

上述服务端程序启动后,将会监听本地的8096端口,并处理客户端的tcp连接请求。我们可以用golang实现一个客户端程序连接上述服务端并进行RPC调用。


$GOPATH/src/test/rpc/jsonrpc_client.go


package main


import (

    "fmt"

    "log"

    "net/rpc/jsonrpc"

)


//算数运算请求结构体

type ArithRequest struct {

    A int

    B int

}


//算数运算响应结构体

type ArithResponse struct {

Pro int //乘积

Quo int //商

Rem int //余数

}


func main() {

    conn, err := jsonrpc.Dial("tcp", "127.0.0.1:8096")

    if err != nil {

        log.Fatalln("dailing error: ", err)

    }


    req := ArithRequest{9, 2}

    var res ArithResponse


err = conn.Call("Arith.Multiply", req, &res) //乘法运算

    if err != nil {

        log.Fatalln("arith error: ", err)

    }

    fmt.Printf("%d * %d = %d\n", req.A, req.B, res.Pro)


    err = conn.Call("Arith.Divide", req, &res)

    if err != nil {

        log.Fatalln("arith error: ", err)

    }

    fmt.Printf("%d / %d, quo is %d, rem is %d\n", req.A, req.B, res.Quo, res.Rem)

}

protorpc库

为了实现跨语言调用,在golang中实现RPC方法的时候我们应该选择一种跨语言的数据编解码方式,比如JSON,上述的jsonrpc可以满足此要求,但是也存在一些缺点,比如不支持http传输,数据编解码性能不高等。于是呢,一些第三方rpc库都选择采用protobuf进行数据编解码,并提供一些服务注册代码自动生成功能。下面的例子我们使用protobuf来定义RPC方法及其请求响应参数,并使用第三方的protorpc库来生成RPC服务注册代码。


首先,需要安装protobuf及protoc可执行命令,可以参考此篇文章:protobuf快速上手指南


然后,我们编写一个proto文件,定义要实现的RPC方法及其相关参数。


$GOPATH/src/test/rpc/pb/arith.proto


syntax = "proto3";

package pb;


//算术运算请求结构

message ArithRequest {

    int32 a = 1;

    int32 b = 2;

}


//算术运算响应结构

message ArithResponse {

int32 pro = 1;  //乘积

int32 quo = 2;  //商

int32 rem = 3;  //余数

}


// rpc方法

service ArithService {

rpc multiply (ArithRequest) returns (ArithResponse);    //乘法运算方法

rpc divide (ArithRequest) returns (ArithResponse);      //除法运算方法

}

接下来我们需要根据上述定义的arith.proto文件生成RPC服务代码。

要先安装protorpc库:go get github.com/chai2010/protorpc

然后使用protoc工具生成代码:protoc --go_out=plugin=protorpc=. arith.proto

执行protoc命令后,在与arith.proto文件同级的目录下生成了一个arith.pb.go文件,里面包含了RPC方法定义和服务注册的代码。


基于生成的arith.pb.go代码我们来实现一个rpc服务端


$GOPATH/src/test/rpc/protorpc_server.go


package main


import (

    "errors"

    "test/rpc/pb"

)


//算术运算结构体

type Arith struct {

}


//乘法运算方法

func (this *Arith) Multiply(req *pb.ArithRequest, res *pb.ArithResponse) error {

    res.Pro = req.GetA() * req.GetB()

    return nil

}


//除法运算方法

func (this *Arith) Divide(req *pb.ArithRequest, res *pb.ArithResponse) error {

    if req.GetB() == 0 {

        return errors.New("divide by zero")

    }

    res.Quo = req.GetA() / req.GetB()

    res.Rem = req.GetA() % req.GetB()

    return nil

}


func main() {

    pb.ListenAndServeArithService("tcp", "127.0.0.1:8097", new(Arith))

}

运行上述程序,将会监听本地的8097端口并接收客户端的tcp连接。


基于ariti.pb.go再来实现一个客户端程序。


$GOPATH/src/test/protorpc_client.go


package main


import (

    "fmt"

    "log"

    "test/rpc/pb"

)


func main() {

    conn, err := pb.DialArithService("tcp", "127.0.0.1:8097")

    if err != nil {

        log.Fatalln("dailing error: ", err)

    }

    defer conn.Close()


    req := &pb.ArithRequest{9, 2}


    res, err := conn.Multiply(req)

    if err != nil {

        log.Fatalln("arith error: ", err)

    }

    fmt.Printf("%d * %d = %d\n", req.GetA(), req.GetB(), res.GetPro())


    res, err = conn.Divide(req)

    if err != nil {

        log.Fatalln("arith error ", err)

    }

    fmt.Printf("%d / %d, quo is %d, rem is %d\n", req.A, req.B, res.Quo, res.Rem)

}

ڡǕ��_'�


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:兄弟连区块链培训

查看原文:兄弟连区块链培训分享Go语言中获取字符串长度的方法

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1099 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传