【go】函數類型的作用

Go 語言函數類型的巧妙應用

函數類型在 Go 語言中非常強大,允許將函數作為值進行傳遞和操作。下面詳細介紹函數類型的各種妙用:

1. 回調函數

// 定義一個函數類型
type Callback func(int) int// 接受回調函數的函數
func processData(data []int, callback Callback) []int {result := make([]int, len(data))for i, v := range data {result[i] = callback(v)}return result
}// 使用示例
func main() {numbers := []int{1, 2, 3, 4, 5}// 使用匿名函數作為回調doubled := processData(numbers, func(x int) int {return x * 2})// 使用已定義函數作為回調squared := processData(numbers, square)fmt.Println(doubled)  // [2 4 6 8 10]fmt.Println(squared)  // [1 4 9 16 25]
}func square(x int) int {return x * x
}

2. 策略模式實現

type PaymentStrategy func(amount float64) boolfunc processPayment(amount float64, strategy PaymentStrategy) bool {return strategy(amount)
}// 各種支付策略
func creditCardPayment(amount float64) bool {// 信用卡支付邏輯return true
}func alipayPayment(amount float64) bool {// 支付寶支付邏輯return true
}// 使用示例
func pay(amount float64, paymentMethod string) bool {switch paymentMethod {case "credit":return processPayment(amount, creditCardPayment)case "alipay":return processPayment(amount, alipayPayment)default:return false}
}

3. 裝飾器模式

type HttpHandler func(w http.ResponseWriter, r *http.Request)// 日志裝飾器
func LoggingDecorator(handler HttpHandler) HttpHandler {return func(w http.ResponseWriter, r *http.Request) {fmt.Printf("Request: %s %s\n", r.Method, r.URL.Path)handler(w, r)fmt.Println("Request completed")}
}// 認證裝飾器
func AuthDecorator(handler HttpHandler) HttpHandler {return func(w http.ResponseWriter, r *http.Request) {// 檢查認證信息if authenticate(r) {handler(w, r)} else {http.Error(w, "Unauthorized", http.StatusUnauthorized)}}
}// 使用裝飾器
func main() {http.HandleFunc("/api/data", LoggingDecorator(AuthDecorator(handleData)))http.ListenAndServe(":8080", nil)
}func handleData(w http.ResponseWriter, r *http.Request) {// 業務邏輯
}

4. 函數選項模式

type Server struct {host stringport inttimeout time.DurationmaxConn int
}type ServerOption func(*Server)// 創建Server的選項函數
func WithHost(host string) ServerOption {return func(s *Server) {s.host = host}
}func WithPort(port int) ServerOption {return func(s *Server) {s.port = port}
}func WithTimeout(timeout time.Duration) ServerOption {return func(s *Server) {s.timeout = timeout}
}func WithMaxConn(maxConn int) ServerOption {return func(s *Server) {s.maxConn = maxConn}
}// 創建服務器
func NewServer(options ...ServerOption) *Server {// 設置默認值server := &Server{host:    "localhost",port:    8080,timeout: 30 * time.Second,maxConn: 100,}// 應用所有選項for _, option := range options {option(server)}return server
}// 使用示例
func main() {server := NewServer(WithHost("example.com"),WithPort(9000),WithTimeout(60 * time.Second),)// 使用server...
}

5. 中間件鏈

type Middleware func(http.Handler) http.Handler// 中間件鏈
func Chain(middlewares ...Middleware) Middleware {return func(next http.Handler) http.Handler {for i := len(middlewares) - 1; i >= 0; i-- {next = middlewares[i](next)}return next}
}// 使用示例
func main() {handler := http.HandlerFunc(finalHandler)// 創建中間件鏈chain := Chain(loggingMiddleware,authMiddleware,rateLimitMiddleware,)// 應用中間件鏈http.Handle("/api", chain(handler))http.ListenAndServe(":8080", nil)
}

6. 延遲執行與鉤子函數

type ShutdownHook func()type App struct {shutdownHooks []ShutdownHook
}func (a *App) AddShutdownHook(hook ShutdownHook) {a.shutdownHooks = append(a.shutdownHooks, hook)
}func (a *App) Shutdown() {// 按照注冊順序的相反順序執行鉤子for i := len(a.shutdownHooks) - 1; i >= 0; i-- {a.shutdownHooks[i]()}
}// 使用示例
func main() {app := &App{}// 注冊數據庫關閉鉤子app.AddShutdownHook(func() {fmt.Println("關閉數據庫連接")})// 注冊文件清理鉤子app.AddShutdownHook(func() {fmt.Println("清理臨時文件")})// 應用運行...// 關閉應用app.Shutdown()
}

7. 操作集合的函數

type FilterFunc func(int) bool
type MapFunc func(int) int
type ReduceFunc func(int, int) int// 過濾集合
func Filter(nums []int, filter FilterFunc) []int {result := []int{}for _, n := range nums {if filter(n) {result = append(result, n)}}return result
}// 映射集合
func Map(nums []int, mapper MapFunc) []int {result := make([]int, len(nums))for i, n := range nums {result[i] = mapper(n)}return result
}// 歸約集合
func Reduce(nums []int, initialValue int, reducer ReduceFunc) int {result := initialValuefor _, n := range nums {result = reducer(result, n)}return result
}// 使用示例
func main() {numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}// 過濾偶數evens := Filter(numbers, func(n int) bool {return n%2 == 0})// 將數字翻倍doubled := Map(evens, func(n int) int {return n * 2})// 求和sum := Reduce(doubled, 0, func(acc, n int) int {return acc + n})fmt.Println("結果:", sum) // 60
}

8. 依賴注入

type UserRepository interface {FindByID(id int) (User, error)
}type UserService struct {repo UserRepository
}func NewUserService(repo UserRepository) *UserService {return &UserService{repo: repo}
}// 測試時可以輕松注入模擬實現
func TestUserService(t *testing.T) {mockRepo := &MockUserRepository{FindByIDFunc: func(id int) (User, error) {return User{ID: id, Name: "測試用戶"}, nil},}service := NewUserService(mockRepo)// 測試 service...
}

9. 自定義排序

type Person struct {Name stringAge  int
}type SortBy func(p1, p2 *Person) booltype PersonSorter struct {people []Personless   SortBy
}func (s PersonSorter) Len() int           { return len(s.people) }
func (s PersonSorter) Swap(i, j int)      { s.people[i], s.people[j] = s.people[j], s.people[i] }
func (s PersonSorter) Less(i, j int) bool { return s.less(&s.people[i], &s.people[j]) }// 使用示例
func main() {people := []Person{{"張三", 30},{"李四", 25},{"王五", 35},}// 按年齡排序sort.Sort(PersonSorter{people: people,less: func(p1, p2 *Person) bool {return p1.Age < p2.Age},})fmt.Println("按年齡排序:", people)// 按姓名排序sort.Sort(PersonSorter{people: people,less: func(p1, p2 *Person) bool {return p1.Name < p2.Name},})fmt.Println("按姓名排序:", people)
}

10. 惰性計算

type LazyEval func() interface{}func computeExpensiveValue() LazyEval {computed := falsevar result interface{}return func() interface{} {if !computed {fmt.Println("執行昂貴計算...")// 模擬耗時操作time.Sleep(1 * time.Second)result = 42computed = true}return result}
}// 使用示例
func main() {// 創建惰性計算lazy := computeExpensiveValue()fmt.Println("惰性計算創建后,尚未執行計算")// 調用時才執行實際計算value := lazy()fmt.Println("第一次獲取值:", value)// 再次調用不會重復計算value = lazy()fmt.Println("第二次獲取值:", value)
}

函數類型使 Go 擁有了函數式編程的部分能力,同時保持了語言的簡潔性和性能,這使得它在構建靈活、可測試和可維護的代碼時非常有價值。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/72617.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72617.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/72617.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

每日一題--進程與協程的區別

進程是什么&#xff1f; 進程&#xff08;Process&#xff09; 是操作系統進行 資源分配和調度的基本單位&#xff0c;代表一個正在執行的程序實例。每個進程擁有獨立的虛擬地址空間、代碼、數據和系統資源&#xff08;如文件句柄、網絡端口等&#xff09;。進程之間通過 IPC&…

關于deepseek R1模型分布式推理效率分析

1、引言 DeepSeek R1 采用了混合專家&#xff08;Mixture of Experts&#xff0c;MoE&#xff09;架構&#xff0c;包含多個專家子網絡&#xff0c;并通過一個門控機制動態地激活最相關的專家來處理特定的任務 。DeepSeek R1 總共有 6710 億個參數&#xff0c;但在每個前向傳播…

二叉樹算法題實戰:從遍歷到子樹判斷

目錄 一、引言 二、判斷兩棵二叉樹是否相同 思路 代碼實現 注意點 三、二叉樹的中序遍歷 思路 代碼實現 注意點 四、判斷一棵樹是否為另一棵樹的子樹 思路 代碼實現 注意點 ?編輯 五、補充 一、引言 作者主頁&#xff1a;共享家9527-CSDN博客 作者代碼倉庫&am…

【開原寶藏】30天學會CSS - DAY1 第一課

下面提供一個由淺入深、按步驟拆解的示例教程&#xff0c;讓你能從零開始&#xff0c;逐步理解并實現帶有旋轉及懸停動畫的社交圖標效果。為了更簡單明了&#xff0c;以下示例僅創建四個圖標&#xff08;Facebook、Twitter、Google、LinkedIn&#xff09;&#xff0c;并在每一步…

HarmonyOS第22天:解鎖鴻蒙服務開發

走進鴻蒙服務開發的世界 在移動應用開發的領域中&#xff0c;HarmonyOS 以其獨特的分布式理念和強大的系統能力&#xff0c;為開發者們開辟了一片嶄新的天地。其中&#xff0c;服務開發作為 HarmonyOS 應用開發的關鍵環節&#xff0c;猶如一把神奇的鑰匙&#xff0c;能夠幫助開…

鴻蒙應用程序包HAP的開發與使用

1、HAP是什么&#xff1f; HAP&#xff08;Harmony Ability Package&#xff09;是應用安裝和運行的基本單元。HAP包是由代碼、資源、第三方庫、配置文件等打包生成的模塊包&#xff0c;其主要分為兩種類型&#xff1a;entry和feature。 entry&#xff1a;應用的主模塊&#x…

解決qt中自定插件加載失敗,不顯示問題。

這個問題斷斷續續搞了一天多&#xff0c;主要是版本不匹配問題。 我們先來看下 Based on Qt 6.6.0 → 說明 Qt Creator 本身 是基于 Qt 6.6.0 框架構建的。MSVC 2019, 64-bit → 說明 Qt Creator 是使用 Microsoft Visual C 2019 編譯器&#xff08;64 位&#xff09; 編譯的。…

進程間通信--匿名管道

進程間通信介紹 進程間通信目的 數據傳輸&#xff1a;一個進程需要將它的數據發送給另一個進程資源共享&#xff1a;多個進程之間共享同樣的資源。通知事件&#xff1a;一個進程需要向另一個或一組進程發送消息&#xff0c;通知它&#xff08;它們&#xff09;發生了某種事件&…

vue computed 計算屬性簡述

Vue 的 ?計算屬性&#xff08;Computed Properties&#xff09;? 是 Vue 實例中一種特殊的屬性&#xff0c;用于?聲明式地定義依賴其他數據動態計算得出的值?。它的核心優勢在于能夠自動追蹤依賴關系&#xff0c;并緩存計算結果&#xff0c;避免重復計算&#xff0c;提升性…

CSS塊元素、行內元素、行內塊元素詳解

一、塊元素&#xff08;Block Elements&#xff09; 1.定義與特點 獨占一行&#xff1a;默認情況下&#xff0c;塊元素會從新的一行開始&#xff0c;并且其后的元素也會被推到下一行。可設置寬高&#xff1a;可以自由設置寬度&#xff08;width&#xff09;和高度&#xff08…

Vue3項目中可以嘗試封裝那些組件

在 Vue 3 項目中&#xff0c;組件的封裝可以根據功能、復用性和業務需求進行劃分。以下是一些常見的組件類型&#xff0c;適合封裝為獨立組件&#xff1a; 1. 基礎 UI 組件 按鈕 (Button) 封裝不同樣式、大小、狀態的按鈕。支持 disabled、loading 等狀態。 輸入框 (Input) 封…

2025年AI搜索引擎開源項目全景指南:從核心框架到生態工具

2025年AI搜索引擎開源項目全景指南&#xff1a;從核心框架到生態工具 在人工智能技術迅猛發展的當下&#xff0c;開源項目已成為構建AI搜索引擎的核心驅動力。本文整理9個具有代表性的開源項目&#xff0c;涵蓋搜索框架、擴展生態及底層支持技術&#xff0c;助你快速搭建或優化…

Word 小黑第22套

對應大貓23 續編號&#xff08;編號斷了&#xff0c;從一開始&#xff09;&#xff1a;點編號&#xff0c;再設置編號值 插入以圖標方式顯示的文檔&#xff1a;插入 -對象 -由文件創建 &#xff08;這里要鏈接到文件也要勾選 不然扣一分&#xff09; 一個頁面設為橫向不影響上…

平面波揚聲器 VS球面波揚聲器的原理與優缺點對比

一、核心定義與原理 1、平面波揚聲器 1.1、平面波揚聲器的定義?&#xff1a;通過“相控陣”技術控制聲波相位&#xff0c;使聲波以平行線&#xff08;面&#xff09;定向傳播的揚聲器&#xff0c;聲波近似平面振動&#xff0c;能量集中且衰減緩慢?。 1.2、平面波揚聲器的原…

設計模式之命令設計模式

命令設計模式&#xff08;Command Pattern&#xff09; 請求以命令的形式包裹在對象中&#xff0c;并傳給調用對象。調用對象尋找可以處理該命令的對象&#xff0c;并把該命令傳給相應的對象執行命令&#xff0c;屬于行為型模式命令模式是一種特殊的策略模式&#xff0c;體現的…

EcoVadis新增可持續發展徽章

EcoVadis新增的兩項新徽章旨在進一步激勵和表彰企業在可持續發展方面的努力和成就。以下是這兩項新徽章的概述&#xff1a; 可持續發展之旅徽章&#xff08;Sustainability Journey Badge&#xff09;&#xff1a; 目的&#xff1a;表彰那些在可持續發展方面展現出持續進步和承…

力扣hot100二刷——二叉樹

第二次刷題不在idea寫代碼&#xff0c;而是直接在leetcode網站上寫&#xff0c;“逼”自己掌握常用的函數。 標志掌握程度解釋辦法?Fully 完全掌握看到題目就有思路&#xff0c;編程也很流利??Basically 基本掌握需要稍作思考&#xff0c;或者看到提示方法后能解答???Sl…

從“自習室令牌”到線程同步:探秘鎖與條件變量

目錄 互斥 為什么需要鎖 鎖的原理--互斥 鎖的使用 同步 鎖的問題 條件變量 互斥 為什么需要鎖 先看結果&#xff1a; 以下代碼是我模擬創建線程搶票&#xff0c;由于不加鎖導致票搶到了負數 main.cc: #include<vector> #include<iostream> #include"…

字符串哈希從入門到精通

一、基本概念 字符串哈希是將任意長度的字符串映射為固定長度的哈希值&#xff08;通常為整數&#xff09;的技術&#xff0c;核心目標是實現O(1)時間的子串快速比較和高效查詢。其本質是通過數學運算將字符串轉換為唯一性較高的數值&#xff0c;例如&#xff1a; ??????…

什么是數學建模?數學建模是將實際問題轉化為數學問題

數學建模是將實際問題轉化為數學問題&#xff0c;并通過數學工具進行分析、求解和驗證的過程。 一、數學建模的基本流程 問題分析 ? 明確目標&#xff1a;確定需要解決的核心問題。 ? 簡化現實&#xff1a;識別關鍵變量、忽略次要因素。 ? 定義輸入和輸出&#xff1a;明確模…