golang 实现程序运行时函数动态替换,举例说明动态注入和替换本地方法、系统库方法、第三方库方法,附完整源码实现

golang 实现程序运行时函数动态替换,举例说明动态注入和替换本地方法、系统库方法、第三方库方法,附完整源码实现。

1、先创建一个go文件,把包名设置为main,并写一个main方法;
在这里插入图片描述

2、测试本地方法动态替换

func originFunc() {
    
    
	str := "this is origin func"
	fmt.Println(str)
}

func replaceFunc() {
    
    
	str := "this is replace func"
	fmt.Println(str)
}

func testLocalMethod() {
    
    
	originFunc()
	hook.Hook(originFunc, replaceFunc, nil)
	originFunc()
	fmt.Println("====================")
}

测试结果:

在这里插入图片描述

3、测试系统方法动态替换,以time下的方法为例


func nowTime() time.Time {
    
    
	return time.Date(2022, 1, 1, 0, 0, 0, 0, &time.Location{
    
    })
}

func Local3(t time.Time) time.Time {
    
    
	return time.Date(2022, 1, 1, 0, 0, 0, 0, &time.Location{
    
    })
}

func Local4() time.Time {
    
    
	return time.Date(2022, 1, 1, 0, 0, 0, 0, &time.Location{
    
    })
}


func testSystemLib() {
    
    

	fmt.Println(time.Now())
	hook.Hook(time.Now, nowTime, nil)
	fmt.Println(time.Now())
	fmt.Println("====================")

	t1 := time.Time{
    
    }
	fmt.Println(t1.Local())
	hook.HookMethod(t1, "Local", Local3, nil)
	fmt.Println(t1.Local())
	hook.Hook(t1.Local, Local4, nil)
	fmt.Println(t1.Local())
	fmt.Println("====================")
}

测试结果:

在这里插入图片描述

4、测试第三方库方法,动态注入和替换,以net/http包下http请求方法为例:

func do1(req *http.Request) (*http.Response, error) {
    
    
	return nil, fmt.Errorf("replace request success")
}

func do2(*http.Client, *http.Request) (*http.Response, error) {
    
    
	return nil, fmt.Errorf("replace request success")
}


func ThirdRequest(url, method, token string, data map[string]interface{
    
    }) (error, map[string]interface{
    
    }) {
    
    
	//Method: "OPTIONS" | "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "TRACE" | "CONNECT"
	client := &http.Client{
    
    
		Transport: &http.Transport{
    
    TLSClientConfig: &tls.Config{
    
    InsecureSkipVerify: true}},
	}
	jsonBytes, err := json.Marshal(data)
	if err != nil {
    
    
		fmt.Println("11", err)
		return err, nil
	}
	request, err := http.NewRequest(method, url, bytes.NewReader(jsonBytes))
	if err != nil {
    
    
		fmt.Println("22", err)
		return err, nil
	}
	// 设置请求头
	request.Header.Add("Content-Type", "application/json;charset=utf-8")
	if len(token) > 0 {
    
    
		request.Header.Add("token", token)
	}
	// 设置5秒的超时时间
	client.Timeout = 5 * time.Second

	// 发起请求
	resp, err := client.Do(request)
	if err != nil {
    
    
		return err, nil
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
    
    
		return err, nil
	}

	res := map[string]interface{
    
    }{
    
    }
	err = json.Unmarshal(body, &res)
	if err != nil {
    
    
		return err, nil
	}
	return nil, res
}


func testThirdLib() {
    
    
	params := map[string]interface{
    
    }{
    
    
		"query": "test",
	}
	err, result := ThirdRequest("http://www.baidu.com", "GET", "", params)
	fmt.Println(err, result)
	client := &http.Client{
    
    }
	hook.HookMethod(client, "Do", do2, nil)
	err, result = ThirdRequest("http://www.baidu.com", "GET", "", params)
	fmt.Println(err, result)

}

测试结果:

在这里插入图片描述


完整源码:

package main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"github.com/YouAreOnlyOne/goutils/hook"
	"io/ioutil"
	"net/http"
	"time"
)

func originFunc() {
    
    
	str := "this is origin func"
	fmt.Println(str)
}

func replaceFunc() {
    
    
	str := "this is replace func"
	fmt.Println(str)
}

func do1(req *http.Request) (*http.Response, error) {
    
    
	return nil, fmt.Errorf("replace request success")
}

func do2(*http.Client, *http.Request) (*http.Response, error) {
    
    
	return nil, fmt.Errorf("replace request success")
}

func nowTime() time.Time {
    
    
	return time.Date(2022, 1, 1, 0, 0, 0, 0, &time.Location{
    
    })
}

func Local3(t time.Time) time.Time {
    
    
	return time.Date(2022, 1, 1, 0, 0, 0, 0, &time.Location{
    
    })
}

func Local4() time.Time {
    
    
	return time.Date(2022, 1, 1, 0, 0, 0, 0, &time.Location{
    
    })
}

func testThirdLib() {
    
    
	params := map[string]interface{
    
    }{
    
    
		"query": "test",
	}
	err, result := ThirdRequest("http://www.baidu.com", "GET", "", params)
	fmt.Println(err, result)
	client := &http.Client{
    
    }
	hook.HookMethod(client, "Do", do2, nil)
	err, result = ThirdRequest("http://www.baidu.com", "GET", "", params)
	fmt.Println(err, result)

}

func ThirdRequest(url, method, token string, data map[string]interface{
    
    }) (error, map[string]interface{
    
    }) {
    
    
	//Method: "OPTIONS" | "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "TRACE" | "CONNECT"
	client := &http.Client{
    
    
		Transport: &http.Transport{
    
    TLSClientConfig: &tls.Config{
    
    InsecureSkipVerify: true}},
	}
	jsonBytes, err := json.Marshal(data)
	if err != nil {
    
    
		fmt.Println("11", err)
		return err, nil
	}
	request, err := http.NewRequest(method, url, bytes.NewReader(jsonBytes))
	if err != nil {
    
    
		fmt.Println("22", err)
		return err, nil
	}
	// 设置请求头
	request.Header.Add("Content-Type", "application/json;charset=utf-8")
	if len(token) > 0 {
    
    
		request.Header.Add("token", token)
	}
	// 设置5秒的超时时间
	client.Timeout = 5 * time.Second

	// 发起请求
	resp, err := client.Do(request)
	if err != nil {
    
    
		return err, nil
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
    
    
		return err, nil
	}

	res := map[string]interface{
    
    }{
    
    }
	err = json.Unmarshal(body, &res)
	if err != nil {
    
    
		return err, nil
	}
	return nil, res
}

func testLocalMethod() {
    
    
	originFunc()
	hook.Hook(originFunc, replaceFunc, nil)
	originFunc()
	fmt.Println("====================")
}

func testSystemLib() {
    
    

	fmt.Println(time.Now())
	hook.Hook(time.Now, nowTime, nil)
	fmt.Println(time.Now())
	fmt.Println("====================")

	t1 := time.Time{
    
    }
	fmt.Println(t1.Local())
	hook.HookMethod(t1, "Local", Local3, nil)
	fmt.Println(t1.Local())
	hook.Hook(t1.Local, Local4, nil)
	fmt.Println(t1.Local())
	fmt.Println("====================")
}

func main() {
    
    
	testLocalMethod()
	testSystemLib()
	testThirdLib()

}


更多有用库:

github.com/YouAreOnlyOne/goutils

猜你喜欢

转载自blog.csdn.net/u014374009/article/details/128970159