C語言中文網 目錄
首頁 > Go語言教程 > Go語言函數 閱讀:3,643

Go語言字符串的鏈式處理——操作與數據分離的設計技巧

使用 SQL 語言從數據庫中獲取數據時,可以對原始數據進行排序(sort by)、分組(group by)和去重(distinct)等操作。SQL 將數據的操作與遍歷過程作為兩個部分進行隔離,這樣操作和遍歷過程就可以各自獨立地進行設計,這就是常見的數據與操作分離的設計。

對數據的操作進行多步驟的處理被稱為鏈式處理。本例中使用多個字符串作為數據集合,然后對每個字符串進行一系列的處理,用戶可以通過系統函數或者自定義函數對鏈式處理中的每個環節進行自定義。

首先給出本節完整代碼:
package main

import (
    "fmt"
    "strings"
)

// 字符串處理函數,傳入字符串切片和處理鏈
func StringProccess(list []string, chain []func(string) string) {

    // 遍歷每一個字符串
    for index, str := range list {

        // 第一個需要處理的字符串
        result := str

        // 遍歷每一個處理鏈
        for _, proc := range chain {

            // 輸入一個字符串進行處理,返回數據作為下一個處理鏈的輸入。
            result = proc(result)
        }

        // 將結果放回切片
        list[index] = result
    }
}

// 自定義的移除前綴的處理函數
func removePrefix(str string) string {

    return strings.TrimPrefix(str, "go")
}

func main() {

    // 待處理的字符串列表
    list := []string{
        "go scanner",
        "go parser",
        "go compiler",
        "go printer",
        "go formater",
    }

    // 處理函數鏈
    chain := []func(string) string{
        removePrefix,
        strings.TrimSpace,
        strings.ToUpper,
    }

    // 處理字符串
    StringProccess(list, chain)

    // 輸出處理好的字符串
    for _, str := range list {
        fmt.Println(str)
    }

}

1) 字符串處理函數

字符串處理函數(StringProccess)需要外部提供數據源:一個字符串切片(list[]string),另外還要提供一個鏈式處理函數的切片(chain[]func(string)string),鏈式處理切片中的一個處理函數的定義如下:

func(string)string

這種處理函數能夠接受一個字符串輸入,處理后輸出。

strings 包中將字符串變為小寫就是一種處理函數的形式,strings.ToLower() 函數能夠將傳入的字符串的每一個字符變為小寫,strings.ToLower 定義如下:

func ToLower(s string) string

字符串處理函數(StringProccess)內部遍歷每一個數據源提供的字符串,每個字符串都需要經過一系列鏈式處理函數處理后被重新放回切片,參見下面代碼。

字符串的鏈式處理:
// 字符串處理函數, 傳入字符串切片和處理鏈
func StringProccess(list []string, chain []func(string) string) {

    // 遍歷每一個字符串
    for index, str := range list {

        // 第一個需要處理的字符串
        result := str

        // 遍歷每一個處理鏈
        for _, proc := range chain {

            // 輸入一個字符串進行處理, 返回數據作為下一個處理鏈的輸入
            result = proc(result)
        }

        // 將結果放回切片
        list[index] = result
    }
}
代碼說明如下:
  • 第 2 行,傳入字符串切片 list 作為數據源,一系列的處理函數作為 chain 處理鏈。
  • 第 5 行,遍歷字符串切片的每個字符串,依次對每個字符串進行處理。
  • 第 8 行,將當前字符串保存到 result 變量中,作為第一個處理函數的參數。
  • 第 11 行,遍歷每一個處理函數,將字符串按順序經過這些處理函數處理。
  • 第 14 行,result 變量即是每個處理函數的輸入變量,處理后的變量又會重新保存到 result 變量中。
  • 第 18 行,將處理完的字符串保存回切片中。

2) 自定義的處理函數

處理函數可以是系統提供的處理函數,如將字符串變大寫或小寫,也可以使用自定義函數。本例中的字符串處理的邏輯是使用一個自定義的函數實現移除指定go前綴的過程,參見下面代碼:
// 自定義的移除前綴的處理函數
func removePrefix(str string) string {
    return strings.TrimPrefix(str, "go")
}
此函數使用了 strings.TrimPrefix() 函數實現移除字符串的指定前綴。處理后,移除前綴的字符串結果將通過 removePrefix() 函數的返回值返回。

3) 字符串處理主流程

字符串處理的主流程包含以下幾個步驟:
  1. 準備要處理的字符串列表。
  2. 準備字符串處理鏈。
  3. 處理字符串列表。
  4. 打印輸出后的字符串列表。

詳細流程參考下面的代碼:
func main() {

    // 待處理的字符串列表
    list := []string{
        "go scanner",
        "go parser",
        "go compiler",
        "go printer",
        "go formater",
    }

    // 處理函數鏈
    chain := []func(string) string{
        removePrefix,
        strings.TrimSpace,
        strings.ToUpper,
    }

    // 處理字符串
    StringProccess(list, chain)

    // 輸出處理好的字符串
    for _, str := range list {
        fmt.Println(str)
    }
}
代碼說明如下:
  • 第 4 行,定義字符串切片,字符串包含 go 前綴及空格。
  • 第 13 行,準備處理每個字符串的處理鏈,處理的順序與函數在切片中的位置一致。removePrefix() 為自定義的函數,功能是移除 go 前綴;移除前綴的字符串左邊有一個空格,使用 strings.TrimSpace 移除,這個函數的定義剛好符合處理函數的格式:func(string)string;strings.ToUpper 用于將字符串轉為大寫。
  • 第 20 行,傳入字符串切片和字符串處理鏈,通過 StringProcess() 函數對字符串進行處理。
  • 第 23 行,遍歷字符串切片的每一個字符串,打印處理好的字符串結果。

提示

鏈式處理器是一種常見的編程設計。Netty 是使用 Java 語言編寫的一款異步事件驅動的網絡應用程序框架,支持快速開發可維護的高性能的面向協議的服務器和客戶端,Netty 中就有類似的鏈式處理器的設計。

Netty 可以使用類似的處理鏈對封包進行收發編碼及處理。Netty 的開發者可以分為 3 種:第一種是 Netty 底層開發者,第二種是每個處理環節的開發者,第三種是業務實現者,在實際開發環節中,后兩種開發者往往是同一批開發者。鏈式處理的開發思想將數據和操作拆分、解耦,讓開發者可以根據自己的技術優勢和需求,進行系統開發,同時將自己的開發成果共享給其他的開發者。

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo