成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

手寫編程語言-如何為 GScript 編寫標準庫

開發 前端
在寫標準庫的過程中還會有額外收獲,可以再次閱讀一遍 Go 標準庫的實現流程,換了一種語法實現出來,會加深對 Go 標準庫的理解。

版本更新

最近 GScript 更新了 v0.0.11 版本,重點更新了:

  • Docker運行環境
  • 新增了 byte 原始類型
  • 新增了一些字符串標準庫 Strings/StringBuilder
  • 數組切片語法:int[] b = a[1: len(a)];

具體更新內容請看下文。

前言

前段時間發布了 GScript 的在線 playground

這是一個可以在線運行 GScript 腳本的網站,其本質原理是接收用戶的輸入源碼從而在服務器上運行的服務;這簡直就是后門大開的 XSS 攻擊,為保住服務器我設置了運行 API 的后端服務的用戶權限,這樣可以避免執行一些惡意的請求。

但也避免不了一些用戶執行了一些耗時操作,比如一個死循環、或者是我提供 demo 里的打印楊輝三角。

這本質上是一個遞歸函數,當打印的三角層數過高時便會非常耗時,同時也非常消耗 CPU。

有幾次我去檢查服務器時發現了幾個 CPU 過高的進程,基本上都是這樣的耗時操作,不可避免的會影響到服務器的性能。

使用 Docker

為了解決這類問題,很自然的就能想到可以使用 Docker,所有的資源都和宿主機是隔離開的,無論怎么瞎折騰也不會影響到宿主機。

說干就干,最后修改了 API 執行腳本的地方:

    string fileName = d.unix("Asia/Shanghai") + "temp.gs" ;
s.writeFile(fileName, body, 438);
string pwd = s.getwd();
// string res = s.command("gscript", fileName);
string res = s.command("docker","run","--rm","-v", pwd+":/usr/src/gscript","-w","/usr/src/gscript", "crossoverjie/gscript","gscript", fileName);
s.remove(fileName);
r.body = res;
r.ast = dumpAST(body);
r.symbol=dumpSymbol(body);
ctx.JSON(200, r);

主要修改的就是將直接執行的 GScript 命令修改為了調用 docker 執行。

但其實也還有改進空間,后續新增協程之后可以便可監控運行時間,超時后便會自動 kill 進程。

我也將該 Docker 上傳到了 DockerHub,現在大家想在本地體驗 GScript 的 REPL 時也只需要運行Docker 就能使用。

docker pull crossoverjie/gscript
docker run --rm -it crossoverjie/gscript:latest gscript

當然也可以執行用 Docker 執行 GScript 腳本:

docker run --rm -v $PWD:/usr/src/gscript -w /usr/src/gscript crossoverjie/gscript gscript {yourpath}/temp.gs

編寫 GScript 標準庫?

接下來重點聊聊 GScript 標準庫的事情,其實編寫標準庫是一個費時費力的事情。

現在編譯器已經提供了一些可用的內置函數,借由這些內置函數寫一些常見的工具類是完全沒有問題的。

對寫 GScript 標準庫感謝的朋友可以當做一個參考,這里我打了一個樣,先看下運行效果:

// 字符串工具類
StringBuilder b = StringBuilder();
b.writeString("10");
b.writeString("20");
int l = b.writeString("30");
string s = b.String();
printf("s:%s, len=%d ",s,l);
assertEqual(s,"102030");
byte[] b2 = toByteArray("40");
b.WriteBytes(b2);
s = b.String();
assertEqual(s,"10203040");
println(s);

// Strings 工具類
Strings s = Strings();
string[] elems = {"name=xxx","age=xx"};
string ret = s.join(elems, "&");
println(ret);
assertEqual(ret, "name=xxx&age=xx");

bool b = s.hasPrefix("http://www.xx.com", "http");
println(b);
assertEqual(b,true);
b = s.hasPrefix("http://www.xx.com", "https");
println(b);
assertEqual(b,false);

其中的實現源碼基本上是借鑒了 Go 的標準庫,先來看看 StringBuilder 的源碼:

class StringBuilder{
byte[] buf = [0]{};

// append contents to buf, it returns the length of s
int writeString(string s){
byte[] temp = toByteArray(s);
append(buf, temp);
return len(temp);
}

// append b to buf, it returns the length of b.
int WriteBytes(byte[] b){
append(buf, b);
return len(b);
}

// copies the buffer to a new.
grow(int n){
if (n > 0) {
// when there is not enough space left.
if (cap(buf) - len(buf) < n) {
byte[] newBuf = [len(buf), 2*cap(buf)+n]{};
copy(newBuf, buf);
buf = newBuf;
}
}
}

string String(){
return toString(buf);
}
}

主要就是借助了原始的數組類型以及 toByteArray/toString 字節數組和字符串的轉換函數實現的。

class Strings{
// concatenates the elements of its first argument to create a single string. The separator
// string sep is placed between elements in the resulting string.
string join(string[] elems, string sep){
if (len(elems) == 0) {
return "";
}
if (len(elems) == 1) {
return elems[0];
}

byte[] bs = toByteArray(sep);
int n = len(bs) * (len(elems) -1);
for (int i=0; i < len(elems); i++) {
string s = elems[i];
byte[] bs = toByteArray(s);
n = n + len(bs);
}

StringBuilder sb = StringBuilder();
sb.grow(n);
string first = elems[0];
sb.writeString(first);

string[] remain = elems[1:len(elems)];
for(int i=0; i < len(remain); i++){
sb.writeString(sep);
string r = remain[i];
sb.writeString(r);
}
return sb.String();

}

// tests whether the string s begins with prefix.
bool hasPrefix(string s, string prefix){
byte[] bs = toByteArray(s);
byte[] bp = toByteArray(prefix);
return len(bs) >= len(bp) && toString(bs[0:len(bp)]) == prefix;
}
}

Strings 工具類也是類似的,都是一些內置函數的組合運用;

在寫標準庫的過程中還會有額外收獲,可以再次閱讀一遍 Go 標準庫的實現流程,換了一種語法實現出來,會加深對 Go 標準庫的理解。

所以歡迎感興趣的朋友向 GScript 貢獻標準庫,由于我個人精力有限,實現過程中可能會發現缺少某些內置函數或數據結構,這也沒關系,反饋 issue 后我會盡快處理。

由于目前 GScript 還不支持包管理,所以新增的函數可以創建 Class 來實現,后續支持包或者是 namespace 之后直接將該 Class 遷移過去即可。

本文相關資源鏈接

  • GScript 源碼:https://github.com/crossoverJie/gscript
  • Playground 源碼:https://github.com/crossoverJie/gscript-homepage
  • GScript Docker地址:https://hub.docker.com/r/crossoverjie/gscript
責任編輯:武曉燕 來源: 今日頭條
相關推薦

2022-09-27 08:01:48

遞歸函數GScript

2020-04-15 10:50:19

編程語言工具技術

2015-09-16 17:30:20

安裝Go語言Linux

2017-09-28 16:18:55

語言PythonGo

2022-09-19 08:10:37

運算符函數語言

2020-02-11 09:41:02

Go語言程序員文章

2020-02-05 16:55:11

Go語言程序員文章

2023-04-02 23:13:07

Go語言bufio

2018-04-17 08:41:47

Java機器學習應用iOS

2020-03-30 17:43:13

開源開源項目編寫文檔

2011-11-08 17:11:47

程序員

2017-11-20 13:32:54

微服務數據庫開發

2022-05-05 09:11:33

數據庫加密數據安全

2009-11-16 08:58:43

PHP語言

2019-01-02 13:11:53

GO語言緩存

2024-09-30 08:01:44

2020-10-30 12:42:06

TypeScript編程開發

2023-01-13 18:55:09

游戲Ada編程語言

2011-02-25 10:12:09

GoWeb

2015-03-31 10:26:01

數據庫數據庫事務
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩中 | 久久精品一区二区三区四区 | 精品欧美一区二区在线观看视频 | 国产亚洲精品久久久久动 | 日韩视频在线免费观看 | 亚洲日韩中文字幕一区 | 久一精品 | 国产高清区| 四虎影院新地址 | 日产久久 | 天堂一区二区三区四区 | 欧美色人 | 成人三级在线观看 | 黑色丝袜三级在线播放 | 精品久久一区 | 成人一区二区在线 | 久久丁香| 欧美日韩在线成人 | 成人欧美一区二区三区黑人孕妇 | 97高清国语自产拍 | 国产精品欧美大片 | 国产欧美在线播放 | 日韩精品专区在线影院重磅 | 91精品国产乱码久久久久久 | 亚洲综合精品 | 国产精品久久久久久吹潮 | 亚洲国产精品久久久久婷婷老年 | 国产91精品久久久久久久网曝门 | 国偷自产av一区二区三区 | 日韩精品一区二区三区高清免费 | 玖玖综合网| 日韩综合在线 | 手机在线观看 | 亚洲一区二区三区四区五区午夜 | 免费观看一区二区三区毛片 | 国产视频欧美 | 亚洲欧美一区二区三区国产精品 | 成人午夜在线 | 九九热这里 | 久久高清国产视频 | 日本一二区视频 |