zoukankan      html  css  js  c++  java
  • C#DataTable DataSet DataRow区别详解

    DataSet 是C#中用来存储数据库数据的。其实,它的作用是在内存中模拟数据库。我们现实生活中的数据库从大到小的基本结构类似于:数据库实例,表,列,行。在C#语言中,我们在内存中也模拟出了一个这样的关系型数据模型。对应关系如下表:

    数据库  DataSet

    表    DataTable

    列    DataColumn

    行    DataRow

     DataSet 和 物理数据库是两个客体,要使这两个客体保持一致,就需要使用 DataAdapter 类来同步两个客体。一般来说操作流程是:使用 DataAdapter 把物理数据库中的数据填充到 DataSet 中的 DataTable 里。当我们对内存中的 DataSet 做了增、删、改操作后,可以使用 DataAdapter 同步回数据库

    datatable 中的DataRow 和dataColumn和表中的行、列操作一致,可以先确定Column.ColumnName,然后对row 赋值 

    对DataTable中的元素赋值的方法可以使dt.rows[i][columnName]第i行列名对应下的表格数据;

    dtContent = new DataTable();

     //人员ID列
            dtContent.Columns.Add("userID");
            //人员姓名列
            dtContent.Columns.Add("userName");

     DateTime dtStartDate, dtEndDate, cycleDate;
            if (DateTime.TryParse(startDate, out dtStartDate) && DateTime.TryParse(endDate, out dtEndDate))
            {
                cycleDate = dtStartDate;
                while (dtEndDate >= cycleDate)
                {
                    dtContent.Columns.Add(cycleDate.ToString("yyyy-MM-dd"));//循环添加日期行
                    cycleDate = cycleDate.AddDays(1);
                }
            }

     DataRow dr;
            for (int i = 0; i < objMyErpUser.Count(); i++)
            {
                if (objMyErpUser.Find(i))
                {
                    dr = dtContent.NewRow();
                    dr["userID"] = objMyErpUser.ID;//给id列赋值
                    dr["userName"] = objMyErpUser.USERNAME;//给username列赋值
                    for (int j = 2; j < dtContent.Columns.Count; j++)
                    {
                        cellContent = "";

                        //查看值班表是否有记录
                        dtFindContent = objDutyList.FindByUserId(objMyErpUser.ID, dtContent.Columns[j].ColumnName);
                        for (int k = 0; k < dtFindContent.Rows.Count; k++)
                        {
                            if (cellContent != "")
                            {
                                cellContent += "<br/>";
                            }
                            cellContent += dtFindContent.Rows[k]["ITEM"] + " " + dtFindContent.Rows[k]["OT"] + "小时;";
                        }
                                            dr[j] = cellContent;
                    }

                    dtContent.Rows.Add(dr);//根据column.count大小从第二列开始给时间循环列赋值
                }
            }

    DataSet

    ①属性

    CaseSensitive:用于控制DataTable中的字符串比较是否区分大小写。

    DataSetName:当前DataSet的名称。如果不指定,则该属性值设置为"NewDataSet"。如果将DataSet内容写入XML文件,DataSetName是XML文件的根节点名称。

    DesignMode:如果在设计时使用组件中的DataSet,DesignMode返回True,否则返回False。

    HasErrors:表示DataSet中的DataRow对象是否包含错误。如果将一批更改提交给数据库并将DataAdapter对象的ContinueUpdateOnError属性设置为True,则在提交更改后必须检查DataSet的HasErrors属性,以确定是否有更新失败。

    NameSpacePrefix:指定XML命名空间和前缀

    Relations:返回一个DataRelationCollection对象。

    Tables:检查现有的DataTable对象。通过索引访问DataTable有更好的性能。

    ②方法

    AcceptChangesRejectChanges:接受或放弃DataSet中所有挂起更改。调用AcceptChanges时,RowState属性值为Added或Modified的所有行的RowState属性都将被设置为UnChanged.任何标记为Deleted的DataRow对象将从DataSet中删除。调用RejectChanges时,任何标记为Added的DataRow对象将会被从DataSet中删除,其他修改过的DatRow对象将返回前一状态。

    Clear:清除DataSet中所有DataRow对象。该方法比释放一个DataSet然后再创建一个相同结构的新DataSet要快。

    CloneCopy:使用Copy方法会创建与原DataSet具有相同结构和相同行的新DataSet。使用Clone方法会创建具有相同结构的新DataSet,但不包含任何行。

    GetChanges:返回与原DataSet对象具有相同结构的新DataSet,并且还包含原DataSet中所有挂起更改的行。

    GetXmlGetXmlSchema:使用GetXml方法得到由DataSet的内容与她的架构信息转换为XML格式后的字符串。如果只希望返回架构信息,可以使用GetXmlSchema。

    HasChange:表示DataSet中是否包含挂起更改的DataRow对象。

    Merge:从另一个DataSet、DataTable或现有DataSet中的一组DataRow对象载入数据。

    ReadXmlWriteXml:使用ReadXml方法从文件、TextReader、数据流或者XmlReader中将XML数据载入DataSet中。

    Reset:将DataSet返回为未初始化状态。如果想放弃现有DataSet并且开始处理新的DataSet,使用Reset方法比创建一个DataSet的新实例好。

    ③事件

    MergeFailed:在DataSet的Merge方法发生一个异常时触发。

    2DataTable

    ①属性

    ②方法

    ③事件

    ColumnChanged:在列的内容被改变之后触发

    ColumnChangding:在列的内容被改变之前触发

    RowChanged,RowChanging,RowDeleted,RowDeleting

    3DataColumn

    ①属性

    4DataRow

    ①属性

    HasError:确定行是否包含错误。

    Item:通过指定行的列数,列的名称或DataColumn对象本身,访问列的内容。

    ItemArray:获取或设置行中所有列的值。

    RowError:返回一个包含行错误信息的字符串。

    RowState:返回DataRowState枚举中的值来表示行的当前状态。

    Table:返回DataRow对象所在的DataTable。

    ②方法

    AcceptChangesRejectChanges:提交和放弃挂起更改。

    BeginEditCancelEditEndEdit

    ClearErrors:清除DataRow中所有的错误。

    Delete:Delete方法实际上并不从DataRow表的Row集合中删除该DataRow。当调用DataRow对象的Delete方法时,ADO.NET将该行标记为删除,之后调用SqlDataAdapter对象的Update方法来删除其在数据库中对应的行。

    如果希望彻底删除DataRow,可以调用Delete方法,接着再调用它的AccepteChanges方法,还可以使用DataRowCollection对象的Remove方法完成相同的任务。

    dataset ds =new datast();

    datatable tel =new datatable();

    ds..tables.add(tel);

    string code=ds.tables["tel"].rows[0][0].tostring();

    1、创建DataSet对象:

    DataSet ds = new DataSet("DataSetName");

    2、查看调用SqlDataAdapter.Fill创建的结构

    da.Fill(ds,"Orders");

    DataTable tbl = ds.Table[0];

    foreach(DataColumn col in tbl.Columns)

    Console.WriteLine(col.ColumnName);

    3、查看SqlDataAdapter返回的数据

    ①DataRow对象

    DataTable tbl = ds.Table[0];

    DataRow row = tbl.Row[0];

    Console.WriteLine(ros["OrderID"]);

    检查存储在DataRow中的数据

    DataTable tbl = row.Table;

    foreach(DataColumn col in tbl.Columns)

    Console.WriteLine(row[col]);

    ③检查DatTable中的DataRow对象

    foreach(DataRow row in tbl.Rows)

    DisplayRow(row);

    4、校验DataSet中的数据

    ①校验DataColumn的属性:ReadOnly,AllowDBNull,MaxLength,Unique

    ②DataTable对象的Constrains集合:UiqueConstraints,Primarykey, ForeignkeyConstraints

    通常不必刻意去创建ForeignkeyConstraints,因为当在DataSet的两个DataTable对象之间创建关系时会创建一个。

    ③用SqlDataAdapter.Fill模式来检索模式信息

    5、编写代码创建DataTable对象

    ①创建DataTable对象:

    DataTable tbl = new DataTable("TableName");

    ②将DataTable添加到DataSet对象的Table集合

    DataSet ds = new DataSet();

    DataTable tbl = new DataTable("Customers");

    ds.Tables.Add(tbl);

    DataSet ds = new DataSet();

    DataTable tbl = ds.Tables.Add("Customers");

    DataTable对象只能存在于至多一个DataSet对象中。如果希望将DataTable添加到多个DataSet中,就必须使用Copy方法或Clone方法。Copy方法创建一个与原DataTable结构相同并且包含相同行的新DataTable;Clone方法创建一个与原DataTable结构相同,但没有包含任何行的新DataTable。

    ③为DataTable添加列

    DataTable tbl = ds.Tables.Add("Orders");

    DataColumn col =tbl.Columns.Add("OrderID",typeof(int));

    col.AllowDBNull = false;

    col.MaxLength = 5;

    col.Unique = true;

    tbl.PrimaryKey = new DataColumn[]{tbl.Columns["CustomersID"]};

    当设置主键时,AllowDBNull自动设置为False;

    ④处理自动增量列

    DataSet ds = new DataSet();

    DataTable tbl = ds.Tables.Add("Orders");

    DataColumn col = tbl.Columns.Add("OrderID",typeof(int));

    col.AutoIncrement = true;

    col.AutoIncrementSeed = -1;

    col.AutoIncrementStep = -1;

    col.ReadOnly = true;

    ⑤添加基于表达式的列

    tbl.Columns.Add("ItemTotal",typeof(Decimal),"Quantity*UnitPrice");

    6、修改DataTable内容

    ①添加新DataRow

    DataRow row = ds.Tables["Customers"].NewRow();

    row["CustomerID"] = "ALFKI";

    ds.Tables["Customers"].Rows.Add(row);

    object[] aValues ={"ALFKI","Alfreds","Anders","030-22222"};

    da.Tables["Customers"].LoadDataRow(aValues,false);

    ②修改当前行

    修改行的内容逼供内不会自动修改数据库中相应的内容,对行所做的修改被视为是随后将使用SqlDataAdapter对象来提交交给数据库的待定的更改。

    DataRow rowCustomer;

    rowCustomer = ds.Tables["Custoemrs"].Rows.Find("ANTON");

    if(rowCustomer == null)

        //没有查找客户

    else

    {

        rowCustomer["CompanyName"] ="NewCompanyName";

        rowCustomer["ContactName"] ="NewContactName";

    }

     

    //推荐使用这种方式

    DataRow rowCustomer;

    rowCustomer = ds.Tables["Custoemrs"].Rows.Find("ANTON");

    if(rowCustomer == null)

        //没有查找客户

    else

    {

        rowCustomer.BeginEdit();

        rowCustomer["CompanyName"] ="NewCompanyName";

        rowCustomer["ContactName"] ="NewContactName";

        rowCustomer.EndEdit();

    }

    //null表示不修改该列的数据

    obejct[] aCustomer ={null,"NewCompanyName","NewContactName",null}

    DataRow rowCustomer;

    rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

    rowCustomer.ItemArray = aCustomer;

    ③处理DataRow的空值

    //查看是否为空

    DataRow rowCustomer;

    rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

    if(rowCustomer.IsNull("Phone"))

    Console.WriteLine("It''''s Null");

    else

    Console.WriteLine("It''''s not Null");

     

    //赋予空值

    rowCustomer["Phone"] = DBNull.Value;

    ④删除DataRow

    DataRow rowCustomer;

    rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

    rowCustomer.Delete();

    ⑤清除DataRow

    DataRow rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

    rowCustomer.ItemArray = aCustomer;

    da.Tables["Customers"].Remove(rowCustomer);

    或者

    ds.Tables["Customers"].RemoveAt(intIndex);

    ⑥使用DataRow.RowState属性 :Unchanged,Detached,Added,Modified,Deleted

    private void DemonstrateRowState()

    {

        // Run a function to create a DataTable with one column.

        DataTable myTable = MakeTable();

        DataRow myRow;

        // Create a new DataRow.

        myRow = myTable.NewRow();

        // Detached row.

        Console.WriteLine("New Row " + myRow.RowState);

        myTable.Rows.Add(myRow);

        // New row.

        Console.WriteLine("AddRow " + myRow.RowState);

        myTable.AcceptChanges();

        // Unchanged row.

        Console.WriteLine("AcceptChanges " + myRow.RowState);

        myRow["FirstName"] = "Scott";

        // Modified row.

        Console.WriteLine("Modified " + myRow.RowState);

        myRow.Delete();

        // Deleted row.

        Console.WriteLine("Deleted " + myRow.RowState);

    }

    ⑦检查DataRow中的挂起更改

    DataRow rowCustomer;

    rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

    rowCustomer["CompanyName"] = "NewCompanyName";

    string strNewCompanyName,strOldCompanyName;

    Console.WriteLine(rowCustomer["CompanyName",DataRowVersion.Current]);

    Console.WriteLine(rowCustomer["CompanyName",DataRowVersion.Original]);

    ⑧遍历DataSet

    foreach(DataTable dt in dataSet.Tables)

    foreach(DataRow dr in dt.Rows)

    foreach(DataColumn dc in dr.Table.Columns)

    Console.WriteLine(dr[dc]);

    RowState 介绍

    1. 从不同位置载入 DataRow 后 RowState 的状态
    2. 修改, 更改, 删除后的 DataRow.RowState 转化
    3. 使用 AcceptChanges, RejectChanges, SetAdded, SetModified 方法后 DataRow.RowState 的转化
    4. 使用 ImportRow, Copy 方法后 DataRow.RowState 的转化
    5. 访问不同 RowState 的 DataRow 中的数据
    6. 获取 DataTable 中不同 RowState 的 DataRow

    1. RowState 介绍

    RowState 是 DataRow 很重要的一个属性, 表示 DataRow 当前的状态. RowState 有 Added, Modified, Unchanged, Deleted, Detached 几种, 分别表示 DataRow 被添加, 修改, 无变化, 删除, 从表中脱离. 在调用一些方法或者进行某些操作之后, 这些状态可以相互转化.

    DataAdapter 可以根据 RowState 来决定如何影响数据库等存储位置. 如果 DataRow 的状态为 Added,DataAdapter 将把 DataRow 添加到数据库等存储位置, 对于 Modified, Deleted 则将执行更新和删除操作. 其实, 最终的操作效果还是决定于 DataAdapter 的 SelectCommand, UpdateCommand 等 DbCommand. 如果, 在 UpdateCommand 中写入 Delete 语句或者执行有删除操作的存储过程, 那么状态为 Modified 的 DataRow 最终将在数据库中删除而不是更新. (注: 下文中所说的 DataAdapter 操作均如此.)

    2. 从不同位置载入 DataRow 后 RowState 的状态

    a. 从 xml 文件或者使用 DataTable.Rows.Add(params object[]) 方法添加的 DataRow 的 RowState 为 Added.
    使用上面方式增加的 DataRow, 如果使用 DataAdapter 更新, 将执行 insert 操作, 例如: 添加到 sql server 数据库中.

    b. 如果 DataAdapter.AcceptChangesDuringFill 属性为 true, 使用 DataAdapter.Fill 方法填充的 DataRow的 RowState 为 Unchanged, 否则, 为 Added, 默认 AcceptChangesDuringFill 为 true.
    例如: 默认情况下, 从 sql server 数据库读取的 DataRow, 然后直接使用 DataAdapter 更新的话, 是不会有任何数据被修改的, 因为 DataAdapter 不对状态为 Unchanged 的 DataRow 执行任何操作.

    3. 修改, 更改, 删除后的 DataRow.RowState 转化

    a. 对于状态为 Unchanged 或者 Modified 的 DataRow, 修改数据后的状态为 Modified.
    这表示 DataRow 需要将自己的数据通过 DataAdapter 更新回数据库等存储位置. 因为, DataRow 中的数据可能已经和自己先前的版本不同.

    b. 对于状态为 Added 的 DataRow, 修改数据后仍然为 Added.
    DataAdapter 对状态为 Added 的 DataRow 将执行添加操作. 很明显, 即使修改 DataRow 仍然应该保持状态为 Added, 否则无法在 DataAdapter 更新的时候被添加到数据库等存储位置.

    c. 如果 DataAdapter.AcceptChangesDuringUpdate 属性为 true, 使用 DataAdapter.Update 更新后的DataRow 的状态为 Unchanged, 否则, DataRow 的状态保持不变, 默认 AcceptChangesDuringUpdate 为 true.
    默认情况下, 状态为 Unchanged 说明 DataRow 当前的数据没有经历过改变, 你可以认为和数据库中的数据一致, 但并非都如此.

    d. 对于状态为 Unchanged 的 DataRow, 调用 Delete 方法后状态为 Deleted.
    DataAdapter 对状态为 Deleted 的 DataRow 执行删除操作, 将数据库等存储位置的对应数据删除.

    e. 对于状态为 Added 的 DataRow, 调用 Delete 方法后状态为 Detached.
    Added 状态的 DataRow 可能并不存在于数据库等存储位置, 因此状态转化为 Detached 而不是 Deleted,DataAdapter 不会处理状态为 Detached 的 DataRow.

    f. 使用 DataTable.Rows.Remove 方法移除 DataRow 后, DataRow 状态为 Detached.

    4. 使用 AcceptChanges, RejectChanges, SetAdded, SetModified 方法后 DataRow.RowState 的转化

    a. 状态为 Unchanged, Added, Modified 的 DataRow, 使用 DataRow.AcceptChanges 方法, 行状态将转化为 Unchanged.
    以上三种状态的 DataRow, 其目的相当于添加或者修改数据, 因此接受变化后这些 DataRow 存在于 DataTable 中, 并且状态为 Unchanged. 如果这时使用 DataAdapter 更新, 将不会对数据库等存储位置有任何的影响, 因为状态已经为 Unchanged, 这本应该在 DataAdapter 更新后转化的.

    b. 状态为 Deleted 的 DataRow, 使用 DataRow.AcceptChanges 方法, 行状态转化为 Detached.
    目的为删除数据的 DataRow, 接受变化后就从 DataTable 中脱离, 因此状态变为 Detached.

    c. 状态为 Detached 的 DataRow, 不能使用 DataRow.AcceptChanges 方法.

    d. 状态为 Unchanged, Modified, Deleted 的 DataRow, 使用 DataRow.RejectChanges 方法, 行状态将转化为 Unchanged.
    以上三种状态的 DataRow, 其目的相当于删除或者修改数据, 因此拒绝变化后这些 DataRow 存在于 DataTable 中, 并且状态为 Unchanged. 如果这时使用 DataAdapter 更新, 其情况将类似于 a.

    e. 状态为 Added, Detached 的 DataRow, 使用 DataRow.RejectChanges 方法, 行状态将转化为 Detached.
    状态为 Added 的 DataRow 目的在于添加, 因此拒绝后从 DataTable 脱离, 状态为 Detached.

    f. 对状态为 Unchanged 的 DataRow, 可以使用 DataRow.SetAdded, DataRow.SetModified 方法使行状态转化为 Added 或者 Modified.
    SetAdded, SetModified 方法对状态不是 Unchanged 的 DataRow 使用将抛出异常.

    5. 使用 ImportRow, Copy 方法后 DataRow.RowState 的转化

    a. 使用 DataTable.ImportRow 方法导入 DataRow 后, 导入的 DataRow 和原 DataRow 的行状态一致.
    ImportRow 方法采用复制的方式导入 DataRow, 状态为 Detached 的 DataRow, 无法导入到 DataTable, 但不会产生异常.

    b. 使用 DataTable.Copy 或者 DataSet.Copy 方法, DataRow 的状态保持不变.

    6. 访问不同 RowState 的 DataRow 中的数据

    a. 对于状态为 Added, Unchanged, Modified 的 DataRow, 可以方便的通过 DataRow[<列名>] 访问数据.

    b. 状态为 Deleted 的 DataRow 需要使用 DataRow[<列名>, DataRowVersion.Original] 来访问.
    对于已经调用 Delete 方法的 DataRow, 需要指定访问数据的 Original 版本.

    c. 状态为 Detched 的 DataRow, 似乎没有方法访问其中的数据.
    DataRow 已经从 DataTable 中移除, 这可能使其中的数据无法访问.

    7. 获取 DataTable 中不同 RowState 的 DataRow

    a. 可以通过 DataTable.GetChanges(DataRowState) 得到 DataTable 中不同 RowState 的 DataRow 的副本.
    GetChanges 方法将返回一个新的 DataTable, 其中包含了指定行状态的 DataRow 的副本, 修改这些副本不会影响原 DataTable 中的 DataRow. 如果使用不带参数的 GetChanges 方法将返回包含行状态为 Added, Modified, Deleted 的 DataRow 副本的 DataTable. 可以使用位或运算符 | 组合获取多种状态的 DataRow. 另外, 状态为 Detached 的 DataRow 似乎是无法通过 GetChanges 方法获取的.

     

    DataSet用法一:添加代码创建的表DataTable,设置主键外键,读取及修改Data...

    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    public partial class dataset : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                DataSet ds = new DataSet();
                DataTable dt1 = new DataTable("user");
                DataTable dt2 = new DataTable("book");
               

                dt1.Columns.Add("uid", typeof(Int32));
                dt1.Columns.Add("uname", typeof(string));

                dt2.Columns.Add("bid", typeof(Int32));
                dt2.Columns.Add("bname", typeof(string));
               
                ds.Tables.Add(dt1);
                ds.Tables.Add(dt2);
               
                object[] userdata = new object[2];
                object[] bookdata = new object[2];

                userdata[0] = 1;
                userdata[1] = "wjwu";
              
                bookdata[0] = 1;
                bookdata[1] = "English";

                Session["ds"]=ds;

                dt1.Rows.Add(userdata);
                dt2.Rows.Add(bookdata);

                fill();
            }
            
        }
        private void fill()
        {
            DataSet ds = new DataSet();
            ds = (DataSet)Session["ds"];
            GridView1.DataSource = ds.Tables["user"];
            GridView1.DataBind();

            GridView2.DataSource = ds.Tables["book"];
            GridView2.DataBind();
        }

      
        protected void addrow_Click(object sender, EventArgs e)
        {
           //增加表数据
            DataSet ds = new DataSet();
            ds = (DataSet)Session["ds"];

            object[] add = new object[2];
            add[0] = 2;
            add[1] = "lucy";

            try
            {
                ds.Tables["user"].Rows.Add(add);
                Session["ds"] = ds;
                fill();
            }
            catch (Exception ex)
            {
                Response.Write("<script>alert('" + ex.Message + "')</script>");
            }       
        }
       
        protected void pk_Click(object sender, EventArgs e)
        {
            //设置主键
            DataSet ds = new DataSet();
            ds = (DataSet)Session["ds"];

            UniqueConstraint uc = new UniqueConstraint("userpk", ds.Tables["user"].Columns["uid"],true);
            ds.Tables["user"].Constraints.Add(uc);
           
            Session["ds"] = ds;
            fill();
        }

        protected void fk_Click(object sender, EventArgs e)
        {//设置外键
           
            DataSet ds = new DataSet();
            ds = (DataSet)Session["ds"];
            ForeignKeyConstraint fkc = new ForeignKeyConstraint("userfk", ds.Tables["user"].Columns["uid"], ds.Tables["book"].Columns["bid"]);
            ds.Tables["book"].Constraints.Add(fkc);
            Session["ds"] = ds;
            fill();
        }


        protected void Button1_Click(object sender, EventArgs e)
        {
            DataSet ds = new DataSet();
            ds = (DataSet)Session["ds"];

            Label1.Text = ds.Tables["user"].Rows[0]["uname"].ToString();
        }


        protected void Button2_Click(object sender, EventArgs e)
        {
            DataSet ds = new DataSet();
            ds = (DataSet)Session["ds"];
            ds.Tables["book"].Rows[0]["bname"] = TextBox1.Text;
            Session["ds"] = ds;
            fill();
        }
    }

  • 相关阅读:
    寒宣资料汇编
    Windows邮件客户端
    Dear Menuhin
    2017-11-11 Sa Oct Spider
    2017-11-11 Sa Oct How to open a browser in Python
    skynet游戏服务器框架分享
    钉钉 机器人接入 自定义webhook
    golang语法笔记
    [学习笔记]尝试go-micro开发微服务<第一波>
    [学习笔记]Golang--基础数据类型
  • 原文地址:https://www.cnblogs.com/zlqblog/p/3640777.html
Copyright © 2011-2022 走看看