1 字符串分割
1.1 根据空格进行分割 strings.Fields(s string) []string
s:= " ab cd ef gh ij kl "
arr:=strings.Fields(s)
fmt.Printf("arr:%q\n",arr)
输出 arr:["ab" "cd" "ef" "gh" "ij" "kl"]
注意:分割出来的元素不会是空格,元素内部也不包含空格,元字符串如果存在多个空格也照样进行分割。
1.2 根据某个字符串对另一个字符串进行分割 strings.Split(str string, sep string) []string
str:= "iiaiibiiciiiidiiii"
sep:= "ii"
arr:=strings.Split(str, sep)
fmt.Println("arr:", arr)
输出 arr:["" "a" "b" "c" "" "d" "" ""]
可以看出,这里是直接将分隔符替换成了空字符串,然后组成列表。
注意:当 sep = ""时,会根据""进行分割,即结果为:arr:["i" "i" "a" "i" "i" "b" "i" "i" "c" "i" "i" "i" "i" "d" "i" "i" "i" "i"]
2 InArray:某个元素是否在某个列表里面
func newInArray(needle interface{}, haystack interface{}) bool {
haystackValue := reflect.ValueOf(haystack)
haystackKind := haystackValue.Kind()
if haystackKind == reflect.Slice || haystackKind == reflect.Array {
length := haystackValue.Len()
for i := 0; i < length; i++ {
if haystackValue.Index(i).Interface() == needle {
return true
}
}
}
return false
}
func InArray[T comparable](needle T, haystack []T) bool {
for _, item := range haystack {
if item == needle {
return true
}
}
return false
}
3,字符串前缀判断
package main
func main() {
a := BeginWith("abc", "a")
println(a) // 输出true
}
func BeginWith(fullString string, prefix string) bool {
return fullString[0: len(prefix)] == prefix
}
4,正则过滤字符串
package main
import (
"fmt"
"regexp"
)
func main() {
pattern := "[^A-Za-z0-9_\-\u4e00-\u9fcb\u3400-\u4DB5\u20000-\u2A6D6\u2A700-\u2B734\u2A740-\u2B81D]"
reg1 := regexp.MustCompile(pattern)
if reg1 == nil {
fmt.Println("regexp err")
return
}
match := reg1.ReplaceAllString("abc*def汉字&ghi", "")
fmt.Println(match)
}
输出
abcdef汉字ghi
regexp.Split 正则分割字符串
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile("[0-9]+")
txt := "Have9834a908123great10891819081day!"
split := re.Split(txt, -1)
set := []string{}
for i := range split {
set = append(set, split[i])
}
fmt.Println(set) // ["Have", "a", "great", "day!"]
}
5,用一个变量传入和使用多个类型的参数值
package main
import "fmt"
func main() {
multiParam(1, "a", 3.0)
}
func multiParam(params ...interface{}) {
str := fmt.Sprintf("param0:%d,param1:%s,param2:%f", params...)
fmt.Println(str)
}
这里的 ... 和 PHP 的 ... 使用基本一致。而 ... 后面的 interface{} 表明每个传值的类型可以是不固定的。
输出
param0:1,param1:a,param2:3.000000
6,当数据类型不确定或者不固定时,可以使用interface{},在1.18中,也可以使用 any,它其实就是interface{}的别名。
package main
import (
"fmt"
)
func main() {
var a interface{} // 定义一个interface类型的变量
a = funcA(1)
fmt.Println(a)
a = funcB("b")
fmt.Println(a)
a = funcC(2, "")
fmt.Println(a)
a = funcC(0, "c")
fmt.Println(a)
a = funcC(0, "")
fmt.Println(a)
}
func funcA(intA int) int {
return intA
}
func funcB(stringB string) string {
return stringB
}
// 返回interface类型的数据
func funcC(intA int, stringB string) interface{} {
if intA != 0 {
return intA
}
if stringB != "" {
return stringB
}
return nil
}
输出
1
b
2
c
<nil>
7,判断某个结构体里面是否存在某个方法
package main
import (
"fmt"
"reflect"
)
type HaystackStruct struct{}
func main() {
methodExists := MethodExists(&HaystackStruct{}, "FuncA")
fmt.Println(methodExists)
}
// 要查询的方法
func (hs *HaystackStruct) FuncA(data interface{}, name string) string {
data2 := data.(string) + "===" + name
return data2
}
// 判断结构体方法是否存在
func MethodExists(haystackStruct interface{}, toSearchMethodName string) bool {
if toSearchMethodName == "" {
return false
}
p := reflect.TypeOf(haystack)
// 这里的判断只在1.18版本及以上才适用
if p.Kind() == reflect.Pointer {
p = p.Elem()
}
// 1.16写法
if p.Kind() == reflect.Ptr {
p = p.Elem()
}
// 不是结构体时
if p.Kind() != reflect.Struct {
return false
}
object := reflect.ValueOf(haystackStruct)
// 获取到方法
newMethod := object.MethodByName(toSearchMethodName)
if !newMethod.IsValid() {
return false
}
return true
}
输出
true
8,获取当前方法的名称
package main
import (
"fmt"
"runtime"
"strings"
)
func main() {
funcA()
}
func funcA() {
selfFunctionName := GetSelfFunctionName()
fmt.Println(selfFunctionName)
callerFunctionName := GetCallerFunctionName()
fmt.Println(callerFunctionName)
}
// 获取当前运行方法名称:谁调用此方法,就返回谁的方法名称
func GetSelfFunctionName() string {
pc := make([]uintptr, 1) // 第二个参数至少是1
n := runtime.Callers(2, pc)
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
// 这里输出的堆栈文件、行号、包.方法名称
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
functionList := strings.Split(frame.Function, ".")
if len(functionList) >= 2 {
return functionList[1]
} else {
return functionList[0]
}
}
// 获取上级调用方的方法名称:A调用B,B调用本方法,返回A的名称
func GetCallerFunctionName() string {
pc := make([]uintptr, 1) // 第二个参数至少是1
n := runtime.Callers(2, pc)
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
// 这里输出的堆栈文件、行号、包.方法名称
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
functionList := strings.Split(frame.Function, ".")
return functionList[0]
}
输出
/tmp/sandbox1151095896/prog.go:14 main.funcA
funcA
/tmp/sandbox1151095896/prog.go:17 main.funcA
main
9,根据方法名称和后缀列表拼接实际方法名,然后依次执行。这个方法有一个缺点,就是传参只能是简单的数据类型,不支持struct,原因是Call()方法的参数只能是[]Value 类型,不支持带 key 的数据。
package main
import (
"fmt"
"reflect"
"errors"
)
type StructA struct {
}
type requestStruct struct {
ProjectID string `json:"project_id"`
OrgID string `json:"org_id"`
}
func main() {
requestStruct := requestStruct{
ProjectID: "prj-xxx",
OrgID: "org-yyy",
}
response, err := ProcessMethodsWithSuffix(&StructA{}, "Func", []string{"A", "B"}, requestStruct)
if err != nil {
fmt.Println(fmt.Sprintf("error: %v", err))
}
fmt.Println(fmt.Sprintf("response: %v", response[0]))
}
func (s *StructA) FuncA(param ...interface{}) (interface{}, error) {
return fmt.Sprintf("this is funcA: %v", param...), nil
}
func (s *StructA) FuncB(param ...interface{}) (interface{}, error) {
return fmt.Sprintf("this is funcB: %v", param...), errors.New("empty name")
}
// 依次执行多个方法,每个方法返回一个interface
func ProcessMethodsWithSuffix(structObject interface{}, methodName string, methodSuffixList []string, params ...interface{}) ([]interface{}, error) {
var result []interface{}
// 调用对象
toProcessStruct := reflect.ValueOf(structObject)
// 方法名称,如果传空,就默认用调用方的名称
if methodName == "" {
//methodName = GetCallerFunctionName()
}
if methodName == "" {
return result, nil
}
// 方法后缀列表,默认是Common和Individual
if len(methodSuffixList) == 0 {
methodSuffixList = []string{"A", "B"}
}
if len(methodSuffixList) == 0 {
return result, nil
}
// 参数
toProcessParam := []reflect.Value{}
for _, param := range params {
toProcessParam = append(toProcessParam, reflect.ValueOf(param))
}
// 将方法名和后缀拼接成实际方法名,依次执行,有任何error则return
for _, methodSuffix := range methodSuffixList {
toProcessMethodName := methodName + methodSuffix
if IsMethodExists(structObject, toProcessMethodName) {
processResult := toProcessStruct.MethodByName(toProcessMethodName).Call(toProcessParam)
// 所调用的方法必须只有2个返回值,第二个一定是error类型
if len(processResult) != 2 {
return result, errors.New(fmt.Sprintf("Bad Request: %s", toProcessMethodName))
}
if err, ok := processResult[1].Interface().(error); ok {
return result, errors.New(fmt.Sprintf("%s", err))
}
result = append(result, processResult[0])
}
}
return result, nil
}
// 判断结构体方法是否存在
func IsMethodExists(haystackStruct interface{}, toSearchMethodName string) bool {
if toSearchMethodName == "" {
return false
}
p := reflect.TypeOf(haystackStruct)
if p.Kind() == reflect.Ptr {
p = p.Elem()
}
// 不是结构体时
if p.Kind() != reflect.Struct {
return false
}
object := reflect.ValueOf(haystackStruct)
// 获取到方法
newMethod := object.MethodByName(toSearchMethodName)
if !newMethod.IsValid() {
return false
}
return true
}
输出
error: empty name
response: this is funcA: {prj-xxx org-yyy}
6,类型转换
6.1 int类转字符串
package main
import (
"fmt"
"strconv"
)
func main() {
var a int
a = 1
b := string(a)
fmt.Println(b) // 输出空字符串
a += 1
b = strconv.Itoa(a)
fmt.Println(b) // 输出2
var c int8
c = 8
d := fmt.Sprint(c)
fmt.Println(d) // 输出8
var e int32
e = 32
f := fmt.Sprint(e)
fmt.Println(f) // 输出32
var g int64
g = 64
h := strconv.FormatInt(g, 10)
fmt.Println(h) // 输出64
}
可以看出 int 用 strconv.Itoa(),int8和int32用fmt.Sprint(),int64用 strconv.FormatInt(x, 10) 。
6.2 数值型字符串转成int型
package main
import (
"fmt"
"strconv"
)
func main() {
var a string
a = "123"
b, err := strconv.Atoi(a)
if err != nil {
fmt.Println(fmt.Sprintf("strconv.Atoi err:%+v", err))
}
fmt.Println(b) // 输出123
a = "-456"
c, err := strconv.ParseInt(a, 10, 64)
if err != nil {
fmt.Println(fmt.Sprintf("strconv.ParseInt err:%+v", err))
}
fmt.Println(c) // 输出-456
a = "789"
d, err := strconv.ParseUint(a, 10, 64)
if err != nil {
fmt.Println(fmt.Sprintf("strconv.ParseUint err:%+v", err))
}
fmt.Println(d) // 输出789
}
可以看到,不带符号直接转int可以用 strconv.Atoi(),转特定的位数可以用strconv.ParseInt(),带符号用 strconv.ParseUint()。
7,字符串列表拼接成字符串
package main
import "fmt"
func main() {
a := []string{"Project", "Organization", "Global"}
b := JoinListToString(a, ",")
fmt.Println(b) // 输出"Project,Organization,Global"
}
// JoinListToString 将字符串列表拼接成字符串
func JoinListToString(list []string, glue string) string {
length := len(list)
if length == 0 {
return ""
} else if length == 1 {
return list[0]
}
var result string
for i := 0; i < length; i++ {
if i == length - 1 {
result += list[i]
} else {
result += list[i] + glue
}
}
return result
}
8,判断某个map中是否存在某个key: value, ok := mapA[key] ,ok为true就是存在
package main
import (
"fmt"
)
func main() {
mapA := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
for _, key := range []string{"a", "d"} {
value, ok := mapA[key]
if ok {
fmt.Println(fmt.Sprintf("key:%v exist value: %v", key, value))
} else {
fmt.Println(fmt.Sprintf("key:%v not exist", key))
}
}
}
输出
key:a exist value: 1
key:d not exist
9 根据结构体中某个字段进行排序,可使用 sort.Sort()函数
package main
import (
"fmt"
"sort"
)
type Fruit struct {
Name string
Number int
}
func main() {
items := []Fruit{
{"apple", 7},
{"orange", 3},
{"banana", 6},
{"cherry", 1},
}
// 按Name字段从小到大按字母排序
sort.Slice(items, func(i, j int) bool {
return items[i].Name < items[j].Name
})
fmt.Println(fmt.Sprintf("items: %+v", items))
// 按Number字段从大到小排序
sort.Slice(items, func(i, j int) bool {
return items[i].Number > items[j].Number
})
fmt.Println(fmt.Sprintf("items: %+v", items))
}
输出
items: [{Name:apple Number:7} {Name:banana Number:6} {Name:cherry Number:1} {Name:orange Number:3}]
items: [{Name:apple Number:7} {Name:banana Number:6} {Name:orange Number:3} {Name:cherry Number:1}]