golanginit的簡單介紹

本文目錄一覽:

golang 遇到導入自定義包導入不進去的問題解決

當嘗試了網上所有方法,仍然發現在主文件.go中或者在其他地方引用自定義包時,自動刪除導入的包的情況解決如下:

如你存放地址的包在src/xxx.com中時請通過命令行進入這個文件夾的位置

然後執行go mod init xxx.com/m/v1回車

上述的…/m/v1隨便,這個是按照官方的建議這麼寫的方便維護版本吧?!

再次嘗試引入自定義包,引用方式如下:

xxx.com/m/v1

|_test

| |_test.go

|_main.go

import (

“fmt”

“xxx.com/m/v1/test”

)

獻給被折磨許久的小夥伴們。。。

如何Golang開發Android應用

環境配置好複雜,我不得不嘮叨幾句。

需要下載golang1.4rc版,下載ndk,然後編譯。 然後用go get 下載gobind這個工具, 然後,將寫好的代碼用gobind轉化下,然後使用特殊的編譯命令,將代碼編譯成.so文件,將生成的相關文件,放到android studio的項目中。然後java代碼中,利用jni調用引用的代碼。

… 好,接着往下看吧。

環境準備

一台Linux 64的機器

一個帶有AndroidStudioIDE的開發機器

因為環境配置實在複雜,所以我們引入的docker。

docker pull codeskyblue/docker-goandroid

docker run –rm -ti codeskyblue/docker-goandroid bash

cd example; echo “view example projects

docker起來之後,什麼就都配置好了,NDK啦,java啦,GO的環境變量了,等等,並且還預裝了vim,gradle,tmux,git,syncthing,svn

開始寫代碼

寫代碼之前,先約定下目錄結構

go的代碼都放在src/golib下,編譯使用make.bash編譯腳本,看下這個文件樹

.

|– app.iml

|– build.gradle

|– libs/armeabi-v7a # go編譯生成的so文件

| `– libgojni.so

|– main.go_tmpl # 一個模板文件,先不用管它

|– make.bash # 編譯腳本,用來生成.so和Java代碼

`– src

|– golib

| |– hi

| | |– go_hi�0�2�0�2�0�2 # 自動生成的代碼

| | | `– go_hi.go

| | `– hi.go # 需要編寫的代碼

| `– main.go

`– main

|– AndroidManifest.xml

|– java

| |– go # 自動生成的代碼

| | |– Go.java

| | |– Seq.java

| | `– hi

| | `– Hi.java

| `– me/shengxiang/gohello # 主要的邏輯代碼

| `– MainActivity.java

`– res

我已經寫了一個例子,先直接搞下來

編譯下,試試行不行(就算不行問題應該也不大,因為大問題都被我消滅了)

cd GoHello/app

./make.bash

../gradlew build

一切順利的話在build/outputs/apk下應該可以看到app-debug.apk這個文件。(劇透下,這個文件只有800多K)

編譯好的我放到qiniu上了,可以點擊下載看看

下面可以嘗試改改,我拋磚引玉說下

打開hi.go這個文件

hi.go的內容,比較簡單,我們寫Go代碼主要就是這部分

// Package hi provides a function for saying hello.

package hi

import “fmt”

func Hello(name string) {

fmt.Printf(“Hello, %s!\n”, name)

return “(Go)World”

}

文件末尾添加下面這行代碼

func Welcome(name string) string {

return fmt.Sprintf(“Welcome %s to the go world”, name)

}

使用./make.bash重新編譯下

打開MainActivity.java 修改下OnClickListener事件

button.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

String message = Hi.Welcome(“yourname”);

Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();

}

});

編譯運行下,把生成的apk安裝到手機上試試。

原理解讀(有興趣的接着看)

首先說下gobind這個工具。

go_hi/go_hi.go這個文件時通過gobind這個工具生成的,用來配合一個簡單的程序,生成.so文件

// go_hi.go

package go_hi

import (

“golang.org/x/mobile/bind/seq”

“example/hi”

)

func proxy_Hello(out, in *seq.Buffer) {

param_name := in.ReadUTF16()

hi.Hello(param_name)

}

func init() {

seq.Register(“hi”, 1, proxy_Hello)

}

這個簡單的程序內容是這樣的

// main.go

package main

import (

“golang.org/x/mobile/app”

_ “golang.org/x/mobile/bind/java”

_ “example/hi/go_hi”

)

func main() {

app.Run(app.Callbacks{})

}

src/MyActivity.java文件內容是這樣的

import …

import go.Go; // 引入Go這個包

import go.hi.Hi; // gobind生成的代碼

public class MainActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Go.init(getApplicationContext()); // 初始化兩個線程

Hi.Hello(“world”);

}

}

其中有一句Go.init(…)這裡再看go.Go這個包是什麼樣子的

public final class Go {

// init loads libgojni.so and starts the runtime.

public static void init(Context context) {

… 判斷該函數是否該執行的代碼 — 省略 —

System.loadLibrary(“gojni”); // gojni需要這句

new Thread(“GoMain”) {

public void run() {

Go.run(); // run()是一個native方法

}

}.start();

Go.waitForRun(); // 這個也是一個native方法

// 這部分可以理解為,啟動了一個後台線程不斷的接收結果到緩存中。

new Thread(“GoReceive”) {

public void run() { Seq.receive(); }

}.start();

}

private static boolean running = false;

private static native void run();

private static native void waitForRun();

}

MyActivity.java中還有段代碼是 Hi.Hello(“world”);,打開Hi.java路徑在src/go/hi/Hi.java,這個文件也是gobind生成的,是用來給java方便的調用.so文件

// Hi.java

// File is generated by gobind. Do not edit.

package go.hi;

import go.Seq;

public abstract class Hi {

private Hi() {} // uninstantiable

public static void Hello(String name) {

go.Seq _in = new go.Seq();

go.Seq _out = new go.Seq();

_in.writeUTF16(name);

Seq.send(DESCRIPTOR, CALL_Hello, _in, _out); // 下面接著說

}

private static final int CALL_Hello = 1;

private static final String DESCRIPTOR = “hi”;

}

Seq.send這部分實際上最終調用的是一段go代碼

func Send(descriptor string, code int, req *C.uint8_t, reqlen C.size_t, res **C.uint8_t, reslen *C.size_t) {

fn := seq.Registry[descriptor][code]

in := new(seq.Buffer)

if reqlen 0 {

in.Data = (*[maxSliceLen]byte)(unsafe.Pointer(req))[:reqlen]

}

out := new(seq.Buffer)

fn(out, in)

seqToBuf(res, reslen, out)

}

轉載僅供參考,版權屬於原作者。祝你愉快,滿意請採納哦

Golang什麼時候會觸發GC

Golang採用了三色標記法來進行垃圾回收,那麼在什麼場景下會觸發這個回收動作呢?

源碼主要位於文件 src/runtime/mgc.go go version 1.16

觸發條件從大方面說,可分為 手動觸發 和 系統觸發 兩種方式。手動觸發一般很少用,主要由開發者通過調用 runtime.GC() 函數來實現,而對於系統自動觸發是 運行時 根據一些條件判斷來進行的,這也正是本文要介紹的內容。

不管哪種觸發方式,底層回收機制是一樣的,所以我們先看一下手動觸發,根據它來找系統觸發的條件。

可以看到開始執行GC的是 gcStart() 函數,它有一個 gcTrigger 參數,是一個觸發條件結構體,它的結構體也很簡單。

其實在Golang 內部所有的GC都是通過 gcStart() 函數,然後指定一個 gcTrigger 的參數來開始的,而手動觸髮指定的條件值為 gcTriggerCycle 。 gcStart 是一個很複雜的函數,有興趣的可以看一下源碼實現。

對於 kind 的值有三種,分別為 gcTriggerHeap 、 gcTriggerTime 和 gcTriggerCycle 。

運行時會通過 gcTrigger.test() 函數來決定是否需要觸發GC,只要滿足上面基中一個即可。

到此我們基本明白了這三種觸發GC的條件,那麼對於系統自動觸發這種,Golang 從一個程序的開始到運行,它又是如何一步一步監控到這個條件的呢?

其實 runtime 在程序啟動時,會在一個初始化函數 init() 里啟用一個 forcegchelper() 函數,這個函數位於 proc.go 文件。

為了減少系統資源佔用,在 forcegchelper 函數里會通過 goparkunlock() 函數主動讓自己陷入休眠,以後由 sysmon() 監控線程根據條件來恢復這個gc goroutine。

可以看到 sysmon() 會在一個 for 語句里一直判斷這個 gcTriggerTime 這個條件是否滿足,如果滿足的話,會將 forcegc.g 這個 goroutine 添加到全局隊列里進行調度(這裡 forcegc 是一個全局變量)。

調度器在調度循環 runtime.schedule 中還可以通過垃圾收集控制器的 runtime.gcControllerState.findRunnabledGCWorker 獲取並執行用於後台標記的任務。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/150723.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-09 02:13
下一篇 2024-11-09 02:14

相關推薦

  • Python簡單數學計算

    本文將從多個方面介紹Python的簡單數學計算,包括基礎運算符、函數、庫以及實際應用場景。 一、基礎運算符 Python提供了基礎的算術運算符,包括加(+)、減(-)、乘(*)、除…

    編程 2025-04-29
  • Python滿天星代碼:讓編程變得更加簡單

    本文將從多個方面詳細闡述Python滿天星代碼,為大家介紹它的優點以及如何在編程中使用。無論是剛剛接觸編程還是資深程序員,都能從中獲得一定的收穫。 一、簡介 Python滿天星代碼…

    編程 2025-04-29
  • Python海龜代碼簡單畫圖

    本文將介紹如何使用Python的海龜庫進行簡單畫圖,並提供相關示例代碼。 一、基礎用法 使用Python的海龜庫,我們可以控制一個小海龜在窗口中移動,並利用它的“畫筆”在窗口中繪製…

    編程 2025-04-29
  • Python櫻花樹代碼簡單

    本文將對Python櫻花樹代碼進行詳細的闡述和講解,幫助讀者更好地理解該代碼的實現方法。 一、簡介 櫻花樹是一種圖形效果,它的實現方法比較簡單。Python中可以通過turtle這…

    編程 2025-04-28
  • Python大神作品:讓編程變得更加簡單

    Python作為一種高級的解釋性編程語言,一直被廣泛地運用於各個領域,從Web開發、遊戲開發到人工智能,Python都扮演着重要的角色。Python的代碼簡潔明了,易於閱讀和維護,…

    編程 2025-04-28
  • 用Python實現簡單爬蟲程序

    在當今時代,互聯網上的信息量是爆炸式增長的,其中很多信息可以被利用。對於數據分析、數據挖掘或者其他一些需要大量數據的任務,我們可以使用爬蟲技術從各個網站獲取需要的信息。而Pytho…

    編程 2025-04-28
  • 如何製作一個簡單的換裝遊戲

    本文將從以下幾個方面,為大家介紹如何製作一個簡單的換裝遊戲: 1. 遊戲需求和界面設計 2. 使用HTML、CSS和JavaScript開發遊戲 3. 實現遊戲的基本功能:拖拽交互…

    編程 2025-04-27
  • Guava Limiter——限流器的簡單易用

    本文將從多個維度對Guava Limiter進行詳細闡述,介紹其定義、使用方法、工作原理和案例應用等方面,並給出完整的代碼示例,希望能夠幫助讀者更好地了解和使用該庫。 一、定義 G…

    編程 2025-04-27
  • 製作一個簡單的管理系統的成本及實現

    想要製作一個簡單的管理系統,需要進行技術選型、開發、測試等過程,那麼這個過程會花費多少錢呢?我們將從多個方面來闡述製作一個簡單的管理系統的成本及實現。 一、技術選型 當我們開始思考…

    編程 2025-04-27
  • 2的32次方-1:一個看似簡單卻又複雜的數字

    對於計算機領域的人來說,2的32次方-1(也就是十進制下的4294967295)這個數字並不陌生。它經常被用來表示IPv4地址或者無符號32位整數的最大值。但實際上,這個數字卻包含…

    編程 2025-04-27

發表回復

登錄後才能評論