斷言與反射——以golang為例

斷言

x.(T) 檢查x的動態類型是否是T,其中x必須是接口值。

簡單使用

func main() {var x interface{}x = 100value1, ok := x.(int)if ok {fmt.Println(value1)}value2, ok := x.(string)if ok {//未打印fmt.Println(value2)}
}

需要注意如果不接受第二個參數就是OK,這里失敗的話則會直接panic,這里還存在一種情況就是x為nil同樣會panic。

func main() {var x interface{}x = "Hello World"value := x.(int)fmt.Println(value)
}
panic: interface conversion: interface {} is string, not int

所以就有這種寫法

switch寫法

func JudgeType(a interface{}) {switch value := a.(type) {case nil:fmt.Println("Type is nil")case int:fmt.Println("int", value)case string:fmt.Println("string:", value)case A:fmt.Println("類型A:", value)case *A:fmt.Println("指針A", value)default:fmt.Println("未匹配")}
}

注意 斷言好像是只能一層一層去處理的 不能一次直接

package mainimport ("encoding/json""fmt"
)func main() {json_str := `{"font_size": 0.4,"lang": "zh","version": "en-v1.2.0.4-t0.3.c","body": [{"content": "最近很多人問我這個概念"},{"content": "在過去的一年里我一直很喜歡"}]}`var json_map map[string]interface{}json.Unmarshal([]byte(json_str), &json_map)//這里直接一步到位 斷言成[]map[string]interface {}  會報錯 panic: interface conversion: interface {} is []interface {}, not []map[string]interface {}//同理[]map[string]string也不可以body := json_map["body"].([]interface{})for _, item := range body {itemMap := item.(map[string]interface{}) //map[string]string依然報錯fmt.Println(itemMap["content"])}}

在這個例子中就是 我們每次只能斷言一個級別 比如第一層斷言是個切片[],第二層斷言是個map[string]

以及注意 interface類型 都要加{}

但是 在處理json的時候

	type body_struct []map[string]stringvar json_map map[string]body_structjson.Unmarshal([]byte(json_str), &json_map)

可以直接這樣,猜測是json這個包內部進行了處理吧

反射

前置知識

用到了前面斷言的知識

Go語言中的變量是分為兩部分的:

? 類型信息:預先定義好的元信息。

? 值信息:程序運行過程中可動態變化的。

在 GoLang 的反射機制中,任何接口值都由是一個具體類型和具體類型的值兩部分組成的。

在這里插入圖片描述
golang變量包含兩個屬性 type和value,這是一個pair對。

type Reader interface {ReadBook( )
}
type Writer interface {WriteBook()
}
//一個具體的結構體
type Book struct {
}
//Book類實現了Reader接口
func(this *Book)ReadBook(){fmt.Println("Read a Book")
}
Book類實現了Writer 接口
func(this *Book)WriteBook(){fmt.Println("Write a Book")
}
func main(){//b:pair<type:Book,value:book{}地址>b := &Book{}//r: pair<type:, value:>var r Reader//r:pair<type:Book, value:book{}地址>r = br.ReadBook()var w writer//r: pair<type:Book,value:book{}地址>w=r.(Writer)//此處的斷言為什么會成功?因為w與r 具體的type是一致

簡單的理解就是 Book實現了兩個接口,斷言成功就是reader指向的book對象可以轉為writer

是什么

反射是靜態語言具有動態屬性的體現

反射是指在程序運行期間對程序本身進行訪問和修改的能力。正常情況程序在編譯時,變量被轉換為內存地址,變量名不會被編譯器寫入到可執行部分。在運行程序時,程序無法獲取自身的信息。支持反射的語言可以在程序編譯期將變量的反射信息,如字段名稱、類型信息、結構體信息等整合到可執行文件中,并給程序提供接口訪問反射信息,這樣就可以在程序運行期獲取類型的反射信息,并且有能力修改它們

有時我們需要寫一個函數,這個函數有能力統一處理各種值類型,而這些類型可能無法共享同一個接口,也可能布局未知,也有可能這個類型在我們設計函數時還不存在,這個時候我們就可以用到反射

反射的功能

  • 反射可以在程序運行期間動態的獲取變量的各種信息,比如變量的類型 類別

  • 如果是結構體,通過反射還可以獲取結構體本身的信息,比如結構體的字段、結構體的方法、結構體的 tag。

  • 通過反射,可以修改變量的值,可以調用關聯的方法

reflect包與基本用法

在 GoLang 中,反射的相關功能由內置的 reflect 包提供,任意接口值在反射中都可以理解為由 reflect.Type 和 reflect.Value 兩部分組成,并 且 reflect 包 提 供 了

  • reflect.TypeOf
  • reflect.ValueOf
    兩個重要函數來獲取任意對象的 Value 和 Type

在這里插入圖片描述

%T不也可以獲取類型么?----可能%T就是通過反射來得到的

reflect.TypeOf()

使用 reflect.TypeOf()函數可以接受任意 interface{}參數,可以獲得任意值的類型對象(reflect.Type),程序通過類型對象可以訪問任意值的類型信息

在反射中關于類型還劃分為兩種:類型(Type)和種類(Kind)

因為在 Go 語言中我們可以使用 type 關鍵字構造很多自定義類型,而種類(Kind)就是指底層的類型,但在反射中,

當需要區分指針、結構體等大品種的類型時,就會用到種類(Kind)。 舉個例子,我們定義了兩個指針類型和兩個結構體類型,通過反射查看它們的類型和種類。

Go 語言的反射中像數組、切片、Map、指針等類型的變量,它們的.Name()都是返回空

import ("fmt""reflect"
)func reflectFn(x interface{}) {// 反射獲取任意變量類型v := reflect.TypeOf(x)name := v.Name() // 類型名稱kind := v.Kind() // 種類(底層類型)fmt.Printf("類型是%v,類型名稱是%v,種類是%v \n", v, name, kind)}// 自定義一個myInt類型
type myInt int// Person結構體
type Person struct {Name stringAge  int
}func main() {a := 10b := "s"// 打印基本類型reflectFn(a) // 類型是int,類型名稱是int,種類是intreflectFn(b) // 類型是string,類型名稱是string,種類是string// 打印自定義類型和結構體類型var i myInt = 3var p = Person{"1",2,}reflectFn(i) // 類型是main.myInt,類型名稱是myInt,種類是intreflectFn(p) // 類型是main.Person,類型名稱是Person,種類是struct// 打印指針類型var f = 25reflectFn(&f) // 類型是*int,類型名稱是,種類是ptr}
與前面x.(type)區別
a.(type)?

是類型斷言中的特殊語法,僅在 switch 語句中使用,用于通過接口變量獲取其動態類型。例如:

switch v := a.(type) {
case int:fmt.Println("int:", v)
case string:fmt.Println("string:", v)
}

該語法直接通過接口值的動態類型進行分支判斷?46。

?reflect.TypeOf(a)?

是反射包中的函數,返回 reflect.Type 接口類型的對象,用于獲取任意值的類型信息。例如:

typeOfA := reflect.TypeOf(a)
fmt.Println(typeOfA.Name(), typeOfA.Kind())

該函數通過反射機制解析值的類型,適用于動態類型檢查?12。

功能與靈活性?

.(type)僅能判斷接口變量的動態類型,無法獲取更詳細的類型元信息(如結構體字段、方法等)。
需在代碼中顯式列出所有可能的類型分支,適用于類型已知或有限的場景?

`?reflect.TypeOf?``返回完整的類型元信息,包括類型名稱(Name)、種類(Kind)、結構體字段、方法等。
支持動態處理任意類型,適用于編寫通用代碼(如序列化、ORM 框架)或需要深度類型分析的場景?

性能開銷?
?a.(type)?
類型斷言是 Go 語言的內置語法,性能開銷極低,幾乎等同于普通的條件判斷?。

?reflect.TypeOf?
反射操作需要運行時動態解析類型信息,涉及額外的內存分配和間接調用,性能開銷較高。應避免在性能敏感的場景中使用?

reflect.ValueOf() 獲取原始值

reflect.ValueOf()返回的是 reflect.Value 類型,其中包含了原始值的值信息。reflect.Value 與原始值之間可以互相轉換
在這里插入圖片描述

func reflectValue(x interface{}) {// 通過反射獲取到值v := reflect.ValueOf(x)fmt.Printf("%v, %T \n", v, v) // 10, reflect.Value,獲取到的類型是reflect.Valuefmt.Printf("%v,%T", v.Int(), v.Int()) // 10,int64,獲取到原始值和類型,因為傳入是數字,所以是v.Int()
}
func main() {var i = 10reflectValue(i)
func reflectValue(x interface{}) {v := reflect.ValueOf(x)kind := v.Kind() // 獲取種類// 判斷底層種類  switch kind {// 是int類型case reflect.Int64:fmt.Println(v.Int())case reflect.Float64:fmt.Println(v.Float())case reflect.String:fmt.Println(v.String())}
}

set通過反射設置變量的值

import ("fmt""reflect"
)func reflectValue(x interface{}) {v := reflect.ValueOf(x)// 如果傳入的值是一個指針地址,那需要通過Elem().Kind()獲取具體種類,Elem()返回 Type 對象所表示的指針指向的數據// 如果只是v.kind,獲取的到的是指針類型kind := v.Elem().Kind() // int64if kind == reflect.Int64 {//  int是SetInt  string是SetString等v.Elem().SetInt(3)}
}func main() {var i = 10// 值類型修改副本不會影響原始值,所以需要通過指針地址reflectValue(&i)fmt.Println(i) // 3}

import (
“fmt”
“reflect”
)

// studen結構體
type Student struct {
Name string json:"name"
Age int json:"age"
Score int json:"score"
}

// 結構體方法 獲取學生信息
func (s Student) GetInfo() string {
return fmt.Sprintf(“姓名%v 年齡%v 成績%v”, s.Name, s.Age, s.Score)

}

// 結構體方法 修改學生信息
func (s *Student) SetInfo(name string, age, score int) {
s.Name = name
s.Age = age
s.Score = score

}

// 結構體方法 打印
func (s Student) PrintInfo() {
fmt.Println(“print info”)

}

func PrintStructField(s interface{}) {
// 獲取類型對象
t := reflect.TypeOf(s)
/*

	通過類型變量里面的Field獲取結構體字段*/
// 通過類型變量.Field(下標)可以獲取結構體的字段對象
field0 := t.Field(0)// 獲取到結構體的Name字段對象
fmt.Println(field0) // {Name  string json:"name" 0 [0] false}fmt.Printf("%#v \n", field0) // reflect.StructField{Name:"Name", PkgPath:"", Type:(*reflect.rtype)(0xe748c80), Tag:"json:\"name\"", Offset:0x0, Index:[]int{0}, Anonymous:false}
// 獲取字段名稱
fmt.Println(field0.Name) // Name
// 獲取字段類型
fmt.Println(field0.Type) // string
// 獲取字段tag - json類型
fmt.Println(field0.Tag.Get("json")) // name/*通過類型變量里面的FieldByName獲取結構體字段
*/
// FieldByName返回兩個值,一個是具體的值,一個是是否成功
field1, ok := t.FieldByName("Age")
if ok {fmt.Println(field1.Name)            // 字段名稱:Agefmt.Println(field1.Type)            // 字段類型:intfmt.Println(field1.Tag.Get("json")) // 字段的json類型的tag :age
}/*通過類型變量的NumField獲取該結構體有多少個字段
*/var count = t.NumField()
fmt.Println(count) // 3

}

func main() {

var student = Student{"小李", 15, 100}
PrintStructField(student)

}

通過值變量獲取結構體值的值信息#
func PrintStructField(s interface{}) {
/*
通過值變量獲取結構體屬性對應的值
*/
v := reflect.ValueOf(s)
// 方式一
fmt.Println(v.FieldByName(“Name”)) // 小李
fmt.Println(v.FieldByName(“Age”)) // 15
// 方式二 可以通過循環獲取所有的屬性值
fmt.Println(v.Field(2)) // 100

}
通過反射修改結構體的屬性值#
func ReflectSetValue(s interface{}) {
// 類型對象
t := reflect.TypeOf(s)
// 值對象
v := reflect.ValueOf(s)
// 判斷傳入的結構體是否是指針類型,因為非指針是值類型,不能修改值,必現使用指針類型
if t.Kind() != reflect.Ptr {
fmt.Println(“傳入的不是指針類型”)
return

	// 判斷傳入的指針是不是結構體指針
} else if t.Elem().Kind() != reflect.Struct {fmt.Println("傳入的不是結構體指針")return
}
// 獲取Name字段的指針值
name := v.Elem().FieldByName("Name")
// 修改屬性值
name.SetString("小王")

}

func main() {

var student = Student{"小李", 15, 100}
// 如果傳入一個值接收者,沒有辦法修改結構體的值,如果要修改對應值,需要傳入指針接收者
ReflectSetValue(&student)
fmt.Println(student.Name) // 小王

}

通過類型變量獲取結構體方法#
// 打印結構體方法
func PrintStructFn(s interface{}) {
t := reflect.TypeOf(s)

// 通過類型變量的Method(下標)獲取結構體的方法
method0 := t.Method(0)    // 下標取的方法和結構體的順序沒有關系,和結構體的ASCII碼有關系
fmt.Println(method0.Name) // 下標為0的方法名:GetInfo
fmt.Println(method0.Type) // func(main.Student) string// 通過MethodByName 獲取結構體方法
// 該方法兩個返回值,一個是方法名,一個是是否有該方法的狀態
method1, ok := t.MethodByName("PrintInfo")
if ok {fmt.Println(method1.Name) // PrintInfofmt.Println(method1.Type) // func(main.Student)}
// 獲取結構體一共有幾個方法
fmt.Println(t.NumMethod()) // 2 Student結構體定義了3個方法,有兩個接收者類型是結構體,有一個接收者類型是指針接收者,如果s接收的是值接收者,只能統計值接收者的方法數量,如果是指針接收者,可以統計所有的方法的數量

}

func main() {

var student = Student{"小李", 15, 100}
PrintStructFn(student)

}

通過值變量執行結構體方法#
func RunStructFn(s interface{}) {
v := reflect.ValueOf(s)
// 方法一 通過下標執行對應的方法,Call傳遞對應參數,nil代表沒有參數
v.Method(1).Call(nil) // print info

// 方法二 通過MethodByName執行對應方法,返回值是一個切片
// 傳入參數調用,Call方法傳入的參數需要是一個reflect.Value類型的切片
var params []reflect.Value
params = append(params, reflect.ValueOf("小李"))
params = append(params, reflect.ValueOf(20))
params = append(params, reflect.ValueOf(95))
v.MethodByName("SetInfo").Call(params)fmt.Println(v.MethodByName("GetInfo").Call(nil)) // [姓名小李 年齡20 成績95]

}

func main() {

var student = Student{"小李", 15, 100}
// 如果傳入一個值接收者,沒有辦法修改結構體的值,如果要修改對應值,需要傳入指針接收者
RunStructFn(&student)

}

應用場景

(1)動態類型檢查

反射可以用于在運行時檢查變量的類型,這在處理未知類型的數據時非常有用。例如,編寫通用函數或庫時,可能需要根據傳入參數的類型執行不同的操作。

func checkType(data interface{}) {t := reflect.TypeOf(data)fmt.Println("Type:", t)
}
(2)動態調用方法

反射可以用于在運行時動態調用對象的方法,這在需要根據條件調用不同方法時非常有用

type MyStruct struct{}func (m *MyStruct) MyMethod() {fmt.Println("MyMethod called")
}func callMethod(obj interface{}, methodName string) {v := reflect.ValueOf(obj)method := v.MethodByName(methodName)if method.IsValid() {method.Call(nil)}
}
(3)結構體字段操作比如處理配置文件

反射可以用于在運行時動態訪問和修改結構體的字段,這在處理配置文件、數據庫映射等場景時非常有用。

type Person struct {Name stringAge  int
}func setField(obj interface{}, fieldName string, value interface{}) {v := reflect.ValueOf(obj).Elem()field := v.FieldByName(fieldName)if field.IsValid() && field.CanSet() {field.Set(reflect.ValueOf(value))}
}
動態綁定配置字段?

通過反射動態解析配置文件(如 YAML、JSON),將鍵值對自動映射到預定義結構體的字段中,無需手動逐字段賦值。
?典型實現?:

讀取配置文件內容后,遍歷結構體的反射元數據,匹配鍵名與字段名(支持大小寫轉換、json/yaml 標簽解析)?。
處理嵌套結構體時,遞歸遍歷子結構體字段,實現復雜配置的自動加載?8。

支持熱加載配置?

因為已經變成二進制文件了 配置新消息變成了一個內存中的結構體 所以我們要用反射才能找到它?或者 因為外部是不確定的 你不知道傳進來的配置文件是啥樣的

通過反射動態更新配置對象,實現運行時重載配置文件(如 SIGHUP 信號觸發)而不重啟服務。

?實現邏輯?:

  • 監聽配置文件變化,重新讀取文件內容并生成新配置對象。
  • 通過反射對比新舊配置對象差異,僅更新發生變化的字段值(避免全局替換導致狀態不一致)?
統一配置處理接口?

編寫通用配置解析函數,支持多種格式(JSON/YAML/TOML)的自動適配。
?代碼示例?:

func LoadConfig(filePath string, config interface{}) error {data, _ := os.ReadFile(filePath)  // 讀取文件val := reflect.ValueOf(config).Elem()// 根據文件后綴選擇解析邏輯(如解析為 map[string]interface{})parsedData := parseByFileType(filePath, data)  // 反射遍歷結構體字段并賦值for key, value := range parsedData {field := val.FieldByName(strings.Title(key))  if field.IsValid() && field.CanSet() {field.Set(reflect.ValueOf(value).Convert(field.Type()))  }}return nil
}
// 調用示例:LoadConfig("config.yaml", &ServerConfig{})  

?說明?:通過反射的 FieldByName 和 Set 方法實現鍵值動態映射,支持類型轉換(如字符串轉 int)?。

處理環境變量與默認值?

結合反射實現配置優先級邏輯(如環境變量 > 配置文件 > 默認值)。

?實現方式?:

-遍歷結構體字段,檢查是否存在 env 標簽(如 env:“PORT”),優先從環境變量讀取值?。
若未配置環境變量或文件字段,通過反射檢查并設置字段的默認值(如 default:“8080” 標簽)?。

?動態校驗配置合法性?

利用反射實現字段類型校驗或自定義規則檢查(如端口號范圍、必填字段)。
?示例邏輯?:

func ValidateConfig(config interface{}) error {t := reflect.TypeOf(config).Elem()v := reflect.ValueOf(config).Elem()for i := 0; i < t.NumField(); i++ {field := t.Field(i)value := v.Field(i)// 檢查必填標簽(如 `required:"true"`)if field.Tag.Get("required") == "true" && value.IsZero() {return fmt.Errorf("字段 %s 必填", field.Name)}}return nil
}

?用途?:防止因配置缺失或格式錯誤導致服務啟動失敗?58。

注意事項

?性能開銷?:反射操作比靜態代碼慢,建議在初始化階段或低頻熱加載場景使用,避免高頻調用?

(4)序列化與反序列化

反射可以用于實現通用的序列化和反序列化功能,例如將結構體轉換為JSON或從JSON解析為結構體

func toJSON(obj interface{}) string {v := reflect.ValueOf(obj)t := reflect.TypeOf(obj)var result stringfor i := 0; i < v.NumField(); i++ {field := t.Field(i)value := v.Field(i)result += fmt.Sprintf("%s: %v\n", field.Name, value.Interface())}return result
}
(5)插件系統

反射可以用于實現插件系統,動態加載和調用插件中的函數或方法。

func loadPlugin(pluginPath string, functionName string) {p, err := plugin.Open(pluginPath)if err != nil {log.Fatal(err)}f, err := p.Lookup(functionName)if err != nil {log.Fatal(err)}f.(func())()
}
(6)依賴注入

反射可以用于實現依賴注入框架,動態地將依賴注入到對象中。

type Service struct {Dependency *Dependency
}func injectDependency(service interface{}, dependency interface{}) {v := reflect.ValueOf(service).Elem()field := v.FieldByName("Dependency")if field.IsValid() && field.CanSet() {field.Set(reflect.ValueOf(dependency))}

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

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

相關文章

Java設計模式:系統性解析與核心模式

一、設計模式三大分類總覽 創建型模式&#xff08;5種&#xff09; 核心目標&#xff1a;對象創建的優化與解耦 單例模式&#xff08;Singleton&#xff09; 工廠模式&#xff08;Factory&#xff09; 抽象工廠模式&#xff08;Abstract Factory&#xff09; 建造者模式&#…

Elasticsearch 向量數據庫,原生支持 Google Cloud Vertex AI 平臺

作者&#xff1a;來自 Elastic Valerio Arvizzigno Elasticsearch 將作為第一個第三方原生語義對齊引擎&#xff0c;支持 Google Cloud 的 Vertex AI 平臺和 Google 的 Gemini 模型。這使得聯合用戶能夠基于企業數據構建完全可定制的生成式 AI 體驗&#xff0c;并借助 Elastics…

408 計算機網絡 知識點記憶(7)

前言 本文基于王道考研課程與湖科大計算機網絡課程教學內容&#xff0c;系統梳理核心知識記憶點和框架&#xff0c;既為個人復習沉淀思考&#xff0c;亦希望能與同行者互助共進。&#xff08;PS&#xff1a;后續將持續迭代優化細節&#xff09; 往期內容 408 計算機網絡 知識…

10-MySQL-性能優化思路

1、優化思路 當我們發現了一個慢SQL的問題的時候,需要做性能優化,一般我們是為了提高SQL查詢更快,一個查詢的流程由下圖的各環節組成,每個環節都會消耗時間,要減少消耗時候需要從各個環節都分析一遍。 2 連接配置優化 第一個環節是客戶端連接到服務端,這塊可能會出現服務…

Docker:安裝與部署 Nacos 的技術指南

1、簡述 Nacos(Dynamic Naming and Configuration Service)是阿里巴巴開源的一個動態服務發現、配置管理和服務治理的綜合解決方案,適用于微服務架構。 Nacos 主要功能: 服務發現與注冊:支持 Dubbo、Spring Cloud 等主流微服務框架的服務發現與注冊。動態配置管理:支持…

【非機動車檢測】用YOLOv8實現非機動車及駕駛人佩戴安全帽檢測

非機動車及駕駛人佩戴安全帽檢測任務的意義主要包括以下幾點&#xff1a; 保障行車安全&#xff1a;非機動車包括自行車、電動車等&#xff0c;佩戴安全帽能夠有效保護騎車人頭部&#xff0c;減少因交通事故造成的頭部傷害風險&#xff0c;提高行車安全系數。 符合交通法規&am…

壹起航:15年深耕互聯網營銷,助力中國工廠出海獲客

在全球化浪潮下&#xff0c;越來越多的中國工廠渴望拓展海外市場&#xff0c;但面臨品牌建立、穩定詢盤獲取及營銷成本降低等多重挑戰。壹起航憑借15年的豐富經驗&#xff0c;整合外貿建站、SEO優化及海外短視頻營銷&#xff0c;為中國工廠提供一站式出海解決方案。 一、外貿獨…

Emacs 折騰日記(二十)——修改emacs的一些默認行為

上一篇我們完成了emacs輸入法的配置以及將emacs配置成了使用vim的操作方式。但是emacs目前有些默認行為我不太喜歡&#xff0c;這節我們一起來修改它 備份設置 我們打開emacs的配置文件所在路徑&#xff0c;發現有大量的~結尾的文件&#xff0c;這是emacs的備份文件。這里&am…

聊透多線程編程-線程基礎-4.C# Thread 子線程執行完成后通知主線程執行特定動作

在多線程編程中&#xff0c;線程之間的同步和通信是一個常見的需求。例如&#xff0c;我們可能需要一個子線程完成某些任務后通知主線程&#xff0c;并由主線程執行特定的動作。本文將基于一個示例程序&#xff0c;詳細講解如何使用 AutoResetEvent 來實現這種場景。 示例代碼…

【網絡安全 | 項目開發】Web 安全響應頭掃描器(提升網站安全性)

原創項目,未經許可,不得轉載。 文章目錄 項目簡介工作流程示例輸出技術棧項目代碼使用說明項目簡介 安全響應頭是防止常見 Web 攻擊(如點擊劫持、跨站腳本攻擊等)的有效防線,因此合理的配置這些頭部信息對任何網站的安全至關重要。 Web 安全響應頭掃描器(Security Head…

使用libcurl編寫爬蟲程序指南

用戶想知道用Curl庫編寫的爬蟲程序是什么樣的。首先&#xff0c;我需要明確Curl本身是一個命令行工具和庫&#xff0c;用于傳輸數據&#xff0c;支持多種協議。而用戶提到的“Curl庫”可能指的是libcurl&#xff0c;這是一個客戶端URL傳輸庫&#xff0c;可以用在C、C等編程語言…

使用pip3安裝PyTorch與PyG,實現NVIDIA CUDA GPU加速

使用python3的pip3命令安裝python依賴庫。 # python3 -V Python 3.12.3 # # pip3 -V pip 25.0.1 from /root/.pyenv/versions/3.12.3/lib/python3.12/site-packages/pip (python 3.12)Usage: pip3 install [options] <package> ...pip3 install [options] -r <re…

五種常用的web加密算法

文章目錄 五種常用Web加密算法實戰及原理詳解1. AES (高級加密標準)原理詳解應用場景實戰代碼&#xff08;Node.js&#xff09; 2. RSA (非對稱加密)原理詳解應用場景實戰代碼&#xff08;Node.js&#xff09; 3. SHA-256 (安全哈希算法)原理詳解應用場景實戰代碼&#xff08;瀏…

深入解析 C++ 設計模式:原理、實現與應用

一、引言 在 C 編程的廣袤領域中&#xff0c;設計模式猶如閃耀的燈塔&#xff0c;為開發者指引著構建高效、可維護軟件系統的方向。設計模式并非神秘莫測的代碼魔法&#xff0c;實際上&#xff0c;我們在日常編程中或許早已與之打過交道。簡單來說&#xff0c;設計模式常常借助…

Python刷題筆記

Python刷題筆記 1、輸出格式化 第一種格式化的輸出&#xff1a; name "jack" age 17 salary 20031.8752 print("你的名字是&#xff1a;%s,今年 %d 歲,工資 %7.2f" % (name,age,salary) ) --------------------------------------- 你的名字是&#…

【Kubernetes】Kubernetes 如何進行日志管理?Fluentd / Loki / ELK 適用于什么場景?

由于 Kubernetes 運行在容器化的環境中&#xff0c;應用程序和系統日志通常分布在多個容器和節點上&#xff0c;傳統的日志管理方法&#xff08;例如直接訪問每個節點的日志文件&#xff09;在 Kubernetes 中不適用。 因此&#xff0c;Kubernetes 引入了集中式日志管理方案&am…

Ansible(8)——循環與條件任務

目錄 一、循環迭代任務&#xff1a; 1、簡單循環&#xff1a; 2、循環字典列表&#xff1a; 3、Ansible 2.5 之前的循環關鍵字&#xff1a; 4、在循環中使用 register 變量&#xff1a; 二、條件任務&#xff1a; 1、使用條件句的常見場景&#xff1a; 2、條件任務語法…

adb|scrcpy的安裝和配置方法|手機投屏電腦|手機聲音投電腦|adb連接模擬器或手機

adb|scrcpy的安裝和配置方法手機投屏電腦|手機聲音投電腦|adb連接模擬器或手機或電視 引言 在數字設備交織的現代生活中&#xff0c;adb&#xff08;Android Debug Bridge&#xff09;與 scrcpy 宛如隱匿的強大工具&#xff0c;極大地拓展了我們操控手機、模擬器乃至智能電視等…

vue3項目集成electron

一、環境準備 1. 確保已安裝 Node.js (建議版本 16.x 或更高) 2. 創建或進入現有 Vue 項目目錄 cd your-vue-project 二、添加 Electron 支持 在項目根目錄執行: vue add electron-builder 執行后會在 `src` 目錄下生成 `background.js` 主進程文件。 三、主進程配置 (ba…

循環神經網絡 - 參數學習之隨時間反向傳播算法

本文中&#xff0c;我們以同步的序列到序列模式為例來介紹循環神經網絡的參數學習。 循環神經網絡中存在一個遞歸調用的函數 &#x1d453;(?)&#xff0c;因此其計算參數梯度的方式和前饋神經網絡不太相同。在循環神經網絡中主要有兩種計算梯度的方式&#xff1a;隨時間反向…