2018年7月7日 星期六

Golang Features


Collection

array

長度固定,元素相同。
實際上可以用interface當類型,所以可放不同類型元素。
array進行slice操作後,產生的是slice,非array。

declare array:

var grid [5][5]int
var buffer [20]byte
create array:

[3]string
[3]string{"a","b","c"}
[...]string{"a","b","c"}

grid[1][0],grid[1][1],grid[1][2]=8,6,3
grid2:=[3][3]int{{1,2,3},{1,2,3}}
cities:=[...]string{"a","b","c"}

slice

長度可變,元素相同。
slice底層是建立array,並引用它。 實際上可以用interface當類型,所以可放不同類型元素。
官方function都是使用slice。
同一個slice出來的slice,因為是引用相同array,
所以其中一個改變,會影響所有對該array的引用。


declare slice:

var grid [][]int

create slice:
不聲明數量,就是slice;聲明數量就是array。

[3]string
make([]Type,length,capacity)
make([]Type,length)
[]int{}
[]string{"a","b","c"}
s:=new([7]string)[:]   //new array然後slice全部,所以s是slice

s:=[]string{"a","b","c","d","e"}
t:=s[:5]
u:=s[3:len(s)-1]
u[1]="x"          //改變原本的array引用,所以影響所有slice


slice操作:

//尾部都不包括
s[n]    //slice n
s[n:m]  //slice n to m-1
s[n:]   //slice n to last
s[:m]   //slice 0 to m-1
s[:]    //slice all

內建函數

make

used to create slice,map,channel

len

append

cap

new

new struce,new array
new得到的是pointer

程式執行時的記憶體模型

程式運行時,作業系統會配置一塊記憶體給他使用。
這塊記憶體存放程式執行時的變數及各項資料。
這塊記憶的配置,是由程式所控制的。
記憶體的配置模型可分為三種,global、stack、heap。
程式執行時的記憶體需求,依據不同類型,配置在不同記憶體中。

其中heap是從該記憶體的最高位址開始配置。
stack是從最低位址開始配置。


global

程式中的全域變數或是static變數,配置在這個區域。
程式運行中,這些變數永遠存在,也就是記憶體都在使用,不會回收。

stack 堆疊/棧

生命週期可被預期的變數或是函數資料,配置在這個區域。
因為可以預期,所以這些記憶體可被系統自動管理,
不再使用時,系統自動回收。

常見的資料有:
區域變數
函數的參數
函數的返回地址

後進先出原則

等整個function執行結束,
整個stack都釋放了。

配置方式

stack使用是分次分配的,
每分配一個稱為一個frame。
從底位址往高位址一個一個分配,
後分配的(push )進去的會先釋放。
也就是後進先出。
取出稱為pop。
也因為後進先出、一層一層疊加的特性,
所以記憶體是從低位址開始使用,較為合理。

heap 堆

程式執行時才動態產生,
無法預期何時產生、數量多少、何時回收,
這些資料則配置在heap區域。
或是使用者要求,例如使用malloc函數。
這時記憶體就要由使用者自行回收,
或是由語言的Garbage Collection機制回收。

若回收不完全,就會產生out of memory的錯誤,
導致系統記憶體越用越少。

配置方式

每次配置一塊記憶體,每塊記憶體之間各自獨立。
從低位址往高位址配置
href="http://http://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html">參考

2016年6月29日 星期三

Unity

UI Event System

1
UnityAction btnBackAction = () => { onBtnClick(); };
btnBack.onClick.AddListener(btnBackAction);

2
inputField.onEndEdit.AddListener(new UnityAction<string>(onFunc));

3
inputField.onEndEdit.AddListener((string value) =>{ onFunc(value); } );

4
inputField.onEndEdit.AddListener(delegate { onFunc(""); });//參數固定

Message System

Message System is a sub system of event system

這種做法,類似於直接呼叫。

//define a message interface
using UnityEngine.EventSystems;
public interface IMessageSystemHandler : IEventSystemHandler {

    void Message1();
    void Message2();
}

//define a MonoBehaviour class
public class EventSys : MonoBehaviour,IMessageSystemHandler 
{

  public void Message1()
    {
    Debug.Log("Message1");
    }
  public void Message2()
    {
        Debug.Log("Message2");
    }
}

//use EventSys in main flow
using UnityEngine.EventSystems;
public class Main : MonoBehaviour 
{


  void Start () {

  //var eventData = new CustomEventData { publicField = 5.0f };
  //usage 1 ,use real time delegate
  //bad for garbage collection 
  //ExecuteEvents.Execute(gameobject, null,(IMessageSystemHandler ms,
BaseEventData b) => ms.Message1());

  //or
  ExecuteEvents.Execute(gameobject, null, MSH2);
  //or  
  ExecuteEvents.Execute(gameobject, null, MSH2);
  Debug.Log("main end");
  }
 

    private void MSH(IMessageSystemHandler handler, BaseEventData data)
    {
        handler.Message1();
    }

    //delegage this function to MSH2
    private ExecuteEvents.EventFunction MSH2 = delegate (IMessageSystemHandler handler, BaseEventData data)
    {
        handler.Message1();
    };

}

Event Manager

http://wiki.unity3d.com/index.php/CSharpEventManager

using UnityEngine;
using System.Collections;
 
public class TestListener : MonoBehaviour, IEventListener
{
    void Start()
    {
        EventManager.instance.AddListener(this as IEventListener, "TestEvent");
    }
 
    bool IEventListener.HandleEvent(IEvent evt)
    {
        string txt = evt.GetData() as string;
        Debug.Log("Event received: " + evt.GetName() + " with data: " + txt);
        return true;
    }
}

Messenger

http://wiki.unity3d.com/index.php/Advanced_CSharp_Messenger

c# Regular Expression

Regular Expression

Regex regularExpression = new Regex("^[a-zA-Z0-9_]*$");


//contains only upper and lowercase letters, numbers, and underscores.




  • * ^ : start of string
  • [ : beginning of character group
  • a-z : any lowercase letter
  • A-Z : any uppercase letter
  • 0-9 : any digit
  • _ : underscore
  • ] : end of character group
  • * : zero or more of the given characters
  • $ : end of string
  • 2016年5月10日 星期二

    VS Code Setting

    Visaul Studio Code Setting

    MS官方說明安裝

    https://marketplace.visualstudio.com/items?itemName=lukehoban.Go 照著安裝即可

    安裝debug工具 delve

    https//github.com/derekparker/delve

    1. 用git取得delve的repository
    2. install mingw-w64(gcc for win)
    3. mingw-32-make install in delve folder
    4. compiled exe file would be in environment %GO%/bin

    2016年5月3日 星期二

    sequelize- javascript ORM for mySQL....

    Define model

    //column option
    field:'field_name'          //field name
    type:Sequelize.STRING       //data type
    allowNull: true             //
    defaultValue:'value'        //default value
    unique: true                //string value Sequelize.STRING 
    unique: 'compositeIndex'    //string value, 不能相同string
    primaryKey: true
    autoIncrement: true         //auto increament column for integer
    comment: 'this is comment'  //comment
    


    var Foo = sequelize.define('foo', {
     // instantiating will automatically set the flag to true if not set
     flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true},
    
     // default values for dates => current time
     myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW },
    
     // setting allowNull to false will add NOT NULL to the column, which means an error will be
     // thrown from the DB when the query is executed if the column is null. If you want to check that a value
     // is not null before querying the DB, look at the validations section below.
     title: { type: Sequelize.STRING, allowNull: false},
    
     // Creating two objects with the same value will throw an error. The unique property can be either a
     // boolean, or a string. If you provide the same string for multiple columns, they will form a
     // composite unique key.
     someUnique: {type: Sequelize.STRING, unique: true},
     uniqueOne: { type: Sequelize.STRING,  unique: 'compositeIndex'},
     uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'}
    
     // The unique property is simply a shorthand to create a unique index.
     someUnique: {type: Sequelize.STRING, unique: true}
     // It's exactly the same as creating the index in the model's options.
     {someUnique: {type: Sequelize.STRING}},
     {indexes: [{unique: true, fields: ['someUnique']}]}
    
     // Go on reading for further information about primary keys
     identifier: { type: Sequelize.STRING, primaryKey: true},
    
     // autoIncrement can be used to create auto_incrementing integer columns
     incrementMe: { type: Sequelize.INTEGER, autoIncrement: true },
    
     // Comments can be specified for each field for MySQL and PG
     hasComment: { type: Sequelize.INTEGER, comment: "I'm a comment!" },
    
     // You can specify a custom field name via the "field" attribute:
     fieldWithUnderscores: { type: Sequelize.STRING, field: "field_with_underscores" },
    
     // It is possible to create foreign keys:
     bar_id: {
       type: Sequelize.INTEGER,
    
       references: {
         // This is a reference to another model
         model: Bar,
    
         // This is the column name of the referenced model
         key: 'id',
    
         // This declares when to check the foreign key constraint. PostgreSQL only.
         deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
       }
     }
    })
    

    也可以reference 其他model

    2016年4月28日 星期四

    javaScript features (ECMAScript6)

    Class

    define

    class Queue {
        _queue;      
      constructor(contents = []) {
        this._queue = [...contents];
      }
      pop() {
        const value = this._queue[0];
        this._queue.splice(0, 1);
        return value;
      }
    

    extends

    class PeekableQueue extends Queue {
      peek() {
        return this._queue[0];
      }
    
    class Account extends Foo {
      constructor(balance) {
        this.balance = balance;
      }
    
      history(done) {
        someLongTask((err, data) => {
          // Do something with data
          done(null, data);
        });
      }
    
      deposit(amount) {
        this.balance += amount;
        return this.balance;
      }
    }
    
    // Currently, you can only declare functions in a class
    Account.types = ['checking', 'savings'];
    

    get,set

    class Account {
      constructor() {
        this.balance = 0;
      }
    
      get underBudget() {
        return this.balance >= 0;
      }
    
      get overBudget() {
        return this.balance < 0;
      }
    }
    
    const myAccount = Account();
    myAccount.balance = 100;
    console.log(myAccount.underBudget); // true
    

    Iterable Class

    可建立iterable class,並且可用generator建立iterator。

    class MyIterable {
      constructor(items) {
        this.items = items;
      }
    
      *[Symbol.iterator]() {
        for (let item of this.items) {
          yield `Hello, ${item}`;
        }
      }
    }
    
    const test = new MyIterable([1, 2, 3, 4, 5]);
    
    for (let item of test) {
      console.log(item); // => Hello, 1...
    }
    

    Map

    let map = new Map(arr);
    
    for (let key of map.keys()) {
      console.log(key);
    }
    
    for (let value of map.values()) {
      console.log(value);
    }
    
    for (let item of map.entries()) {
      console.log(item[0], item[1]
    }
    

    Module

    基本定義與引用

    用ES6 export,就用import;不要用require

    一個文件中不要export與default export一起用

    不要在import中使用*,確保module中有一個default export

    //定義模組 module.js
    
    var privateVar = "privateVar";  
    //不能被外部引用的成員
    export var publicVar = "and this one is public";   
    //export出去,可被外部引用的成員
    
    export function getVar() {
       return privateVar;
    };
    
    //引用模組 use.js
    import { getVar, publicVar } from 'mymodule'; 
    //import getVar及publicVar兩個成員
    console.log(getVar());
    
    //一次引用這個模組的所有可引用成員
    X import 'mm' from 'mymodule';
    X import 'mymodule' as mm;
    //或是這樣
    import * as 'mm' from 'mymodule';  //不建議使用*
    import abc =require('mymodule');
    
    //不一定都有implement
    import defaultMember from "module-name";
    import * as name from "module-name";
    import { member } from "module-name";
    import { member as alias } from "module-name";
    import { member1 , member2 } from "module-name";
    import { member1 , member2 as alias2 , [...] } from "module-name";
    import defaultMember, { member [ , [...] ] } from "module-name";
    import defaultMember, * as name from "module-name";
    import "module-name";
    
    console.log(mm.gerVar());
    

    default export(無命名export) (文件中只有一個成員)

    //------ myFunc.js ------
    export default function () { ... };
    
    //------ main1.js ------
    import myFunc from 'myFunc';
    myFunc();
    
    //------ MyClass.js ------
    export default class { ... };
     
    //------ main2.js ------
    import MyClass from 'MyClass';
    let inst = new MyClass();
    
    

    一個文件中同時有export(一般export)與default export(無命名export)

    //------ underscore.js ------
    export default function (obj) {
        ...
    };
    
    export function each(obj, iterator, context) {
        ...
    }
    export { each as forEach };
    
    //------ main.js ------
    import _, { each } from 'underscore';
    ...
    
    

    default export就是another named export

    //以下兩者相同
    import { default as foo } from 'lib';
    import foo from 'lib';
    
    //以下兩個模組export相同
    //------ module1.js ------
    export default 123;
    
    //------ module2.js ------
    const D = 123;
    export { D as default };
    
    

    commonJS的module

    //------ underscore.js ------
    var _ = function (obj) {
        ...
    };
    var each = _.each = _.forEach =
        function (obj, iterator, context) {
            ...
        };
    module.exports = _;
     
    
    //------ main.js ------
    var _ = require('underscore');
    var each = _.each;
    ...
    
    
    //------ lib.js ------
    var sqrt = Math.sqrt;
    function square(x) {
        return x * x;
    }
    function diag(x, y) {
        return sqrt(square(x) + square(y));
    }
    module.exports = {
        sqrt: sqrt,
        square: square,
        diag: diag,
    };
     
    //------ main.js ------
    var square = require('lib').square;
    var diag = require('lib').diag;
    console.log(square(11)); // 121
    console.log(diag(4, 3)); // 5