首页 文章 精选 留言 我的

精选列表

搜索[快速入门],共10000篇文章
优秀的个人博客,低调大师

GO从入门到进阶教程系列 - 研发高性能ORM框架mysql管理多数据源篇

↵ 上一篇教程我们了解到了基础的GO语法,今天我们来学习如何使用GO开发一个通用的mysql管理器,下面就直接进入步骤环节,代码需要承接上一篇教程的,如有疑问请查看上一篇教程 技术版权归属 广州市金狮网络科技有限公司 (https://kingc.cn/) ,如需商用请联系公司 1. 编写一个多数据源实例的管理器对象,以及改造下之前的DBConfig对象 // 连接管理器 type RDBManager struct { OpenTx bool // 是否开启事务 DsName string // 数据源名称 Db *sql.DB // 非事务实例 Tx *sql.Tx // 事务实例 Errors []error // 操作过程中记录的错误 } // 数据库配置 type DBConfig struct { DsName string // 数据源名称 Host string // 地址IP Port int // 数据库端口 Database string // 数据库名称 Username string // 账号 Password string // 密码 } 2. 编写初始化多个数据源配置的方法,并改造下我们之前的NewMysql方法 // 初始化数据库实例 func NewMysql(conf DBConfig) (*sql.DB, error) { // 定义占位符字符串,使用配置值替换%s和%d link := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", conf.Username, conf.Password, conf.Host, conf.Port, conf.Database) // 打开mysql获得实例对象 db, err := sql.Open("mysql", link) // 打开mysql失败,返回nil对象,以及返回err对象 if err != nil { return nil, errors.New("mysql初始化失败: " + err.Error()) } // 打开mysql成功返回db对象,err=nil return db, nil } var ( MASTER = "MASTER" // 默认主数据源 RDBs = map[string]*RDBManager{} // 初始化时加载数据源到集合 ) // 初始化多个数据库配置文件 func BuildByConfig(input ...DBConfig) { if len(input) == 0 { panic("数据源配置不能为空") } for _, v := range input { db, err := NewMysql(v) panic(err) if len(v.DsName) == 0 { v.DsName = MASTER } rdb := &RDBManager{ Db: db, DsName: v.DsName, } RDBs[v.DsName] = rdb } } 3. 编写获取数据源的方法,包含是否开启事务,数据源名称参数 // 获取数据源,并控制是否开启事务 func GetDB(openTx bool, ds ...string) (*RDBManager, error) { dsName := MASTER if len(ds) > 0 && len(ds[0]) > 0 { dsName = ds[0] } rt := RDBs[dsName] rdb := &RDBManager{ OpenTx: openTx, Db: rt.Db, DsName: rt.DsName, Errors: []error{}, } // 如设置事务,则初始化事务实例 if rdb.OpenTx { tx, err := rdb.Db.Begin() if err != nil { return nil, errors.New("开启事务失败:" + err.Error()) } rdb.Tx = tx } return rdb, nil } 4. 编写释放数据库资源,并提交事务的方法 // 释放资源并提交事务 func (self *RDBManager) Close() { if self.OpenTx { // 开启事务操作逻辑 if len(self.Errors) > 0 { // 如产生异常则回滚事务 self.Tx.Rollback() } else { self.Tx.Commit() // 如无异常则提交事务 } } } 5. 使用获取的数据源进行保存数据操作,我们改造下之前的CRUD方法 // 通过管理器开启事务保存数据 func (self *RDBManager) CRUD1() error { // 编写需要执行的sql createSql := "insert test_user(username, password, age, sex) values(?,?,?,?)" // 预编译sql,事务模式 stmt, err := self.Tx.Prepare(createSql) if err != nil { return errors.New("预编译失败: " + err.Error()) } // 提交编译sql对应参数 ret, err := stmt.Exec("zhangsan", "123456", 18, 1) if err != nil { return errors.New("提交数据失败: " + err.Error()) } // 保存成功后获取自增ID fmt.Println(ret.LastInsertId()) return nil } 6. 编写单元测试用例 // 单元测试 func TestCRUD1(t *testing.T) { // 数据源配置 conf := DBConfig{ DsName: "test", Host: "127.0.0.1", Port: 3306, Database: "test", Username: "root", Password: "123456", } // 初始化数据源 BuildByConfig(conf) // 获取test数据源 rdb, err := GetDB(true, "test") if err != nil { panic(err) } // 释放资源 defer rdb.Close() // 执行保存数据方法 if err := rdb.CRUD1(); err != nil { panic(err) } } 上面我们已经明白了自定义数据源管理器如何实现,通过示例演示操作,下一篇文章我会讲解如何封装对象转sql入库,敬请期待!

优秀的个人博客,低调大师

【Java入门提高篇】Day15 Java泛型再探——泛型通配符及上下边界

上篇文章中介绍了泛型是什么,为什么要使用泛型以及如何使用泛型,相信大家对泛型有了一个基本的了解,本篇将继续讲解泛型的使用,让你对泛型有一个更好的掌握和更深入的认识。 上篇中介绍完泛型之后,是不是觉得泛型挺好用的?既消除了Object的不安全类型转化,又可以很方便的进行类型对象的存取,但是,等一下,有没有考虑到这样的情况。 我们先定义一个水果类: public class Fruit { private String name; public Fruit(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 然后再定义一个苹果类: public class Apple extends Fruit{ public Apple(String name) { super(name); } } 接下来定义一个泛型容器: public class GenericHolder<T> { private T obj; public GenericHolder(){} public GenericHolder(T obj){ this.obj = obj; } public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } } 接下来开始我们的测试: public class Test { /** * 吃水果 * @param fruitHolder */ public static void eatFruit(GenericHolder<Fruit> fruitHolder){ System.out.println("我正在吃 " + fruitHolder.getObj().getName()); } public static void main(String args[]){ //这是一个贴了水果标签的袋子 GenericHolder<Fruit> fruitHolder = new GenericHolder<Fruit>(); //这是一个贴了苹果标签的袋子 GenericHolder<Apple> appHolder = new GenericHolder<Apple>(); //这是一个水果 Fruit fruit = new Fruit("水果"); //这是一个苹果 Apple apple = new Apple("苹果"); //现在我们把水果放进去 fruitHolder.setObj(fruit); //调用一下吃水果的方法 eatFruit(fruitHolder); //贴了水果标签的袋子放水果当然没有问题 //现在我们把水果的子类——苹果放到这个袋子里看看 fruitHolder.setObj(apple); //同样是可以的,其实这时候会发生自动向上转型,apple向上转型为Fruit类型后再传入fruitHolder中 //但不能再将取出来的对象赋值给redApple了 //因为袋子的标签是水果,所以取出来的对象只能赋值给水果类的变量 //无法通过编译检测 redApple = fruitHolder.getObj(); eatFruit(fruitHolder); //放苹果的标签,自然只能放苹果 appHolder.setObj(apple); // 这时候无法把appHolder 传入eatFruit // 因为GenericHolder<Fruit> 和 GenericHolder<Apple>是两种不同的类型 // eatFruit(appHolder); } } 运行结果: 我正在吃 水果 我正在吃 苹果 在这里,我们往eatFruit方法里传入fuitHolder的时候,是可以正常编译的,但是如果将appHolder传入,就无法通过编译了,因为作为参数时,GenericHolder<Fruit> 和 GenericHolder<Apple>是两种不同的类型,所以无法通过编译,那么问题来了,如果我想让eatFruit方法能同时处理GenericHolder<Fruit> 和 GenericHolder<Apple>两种类型怎么办?而且这也是很合理的需求,毕竟Apple是Fruit的子类,能吃水果,为啥不能吃苹果???如果要把这个方法重载一次,未免也有些小题大做了(而且事实上也无法通过编译,具体原因之后会有说明)。 在代码的逻辑里: 苹果 IS-A 水果 装苹果的盘子 NOT-IS-A 装水果的盘子 这个时候,泛型的边界符就有它的用武之地了。我们先来看效果: public class Test { /** * 吃水果 * @param fruitHolder */ public static void eatFruit(GenericHolder<? extends Fruit> fruitHolder){ System.out.println("我正在吃 " + fruitHolder.getObj().getName()); } public static void main(String args[]){ //这是一个贴了水果标签的袋子 GenericHolder<Fruit> fruitHolder = new GenericHolder<Fruit>(); //这是一个贴了苹果标签的袋子 GenericHolder<Apple> appHolder = new GenericHolder<Apple>(); //这是一个水果 Fruit fruit = new Fruit("水果"); //这是一个苹果 Apple apple = new Apple("苹果"); //现在我们把水果放进去 fruitHolder.setObj(fruit); //调用一下吃水果的方法 eatFruit(fruitHolder); //放苹果的标签,自然只能放苹果 appHolder.setObj(apple); // 这时候可以顺利把appHolder 传入eatFruit eatFruit(appHolder); } } 运行结果: 我正在吃 水果 我正在吃 苹果 这里我们只是使用了一点小小的魔法,把参数类型改成了GenericHolder<? extends Fruit>,这样就能将GenericHolder<Apple>类型的参数顺利传入了,怎么样?很好用吧,这就是泛型的边界符,用<? extends Fruit>的形式表示。边界符的意思,自然就是定义一个边界,这里用?表示传入的泛型类型不是固定类型,而是符合规则范围的所有类型,用extends关键字定义了一个上边界,也就是说这里的?可以代表任何继承于Fruit的类型,你也许会问,为什么是上边界,好问题,一图胜千言: 从这个图可以很好的看出这个“上边界”的概念了吧。有上边界,自然有下边界,泛型里使用形如<? super Fruit>的方式使用下边界,此时,?只能代表Fruit及其父类。 (这两个图是抠过来的,不要骂我懒。) 这两种方式基本上解决了我们之前的问题,但是同时,也有一定的限制。 1.上界<? extends T>不能往里存,只能往外取 不要太疑惑,其实很好理解,因为编译器只知道容器里的是Fruit或者Fruit的子类,但不知道它具体是什么类型,所以存的时候,无法判断是否要存入的数据的类型与容器种的类型一致,所以会拒绝set操作。 2.下界<? super T>往外取只能赋值给Object变量,不影响往里存 因为编译器只知道它是Fruit或者它的父类,这样实际上是放松了类型限制,Fruit的父类一直到Object类型的对象都可以往里存,但是取的时候,就只能当成Object对象使用了。 所以如果需要经常往外读,则使用<? extends T>,如果需要经常往外取,则使用<? super T>。 至此,本篇讲解完毕,欢迎大家继续关注! 真正重要的东西,用眼睛是看不见的。

优秀的个人博客,低调大师

HBase编程 API入门系列之delete.deleteColumn和delete.deleteColumns区别(客户端而言)(4)

心得,写在前面的话,也许,中间会要多次执行,连接超时,多试试就好了。 delete.deleteColumn和delete.deleteColumns区别是: deleteColumn是删除某一个列簇里的最新时间戳版本。 delete.deleteColumns是删除某个列簇里的所有时间戳版本。 hbase(main):020:0>desc 'test_table' Table test_table is ENABLED test_table COLUMN FAMILIES DESCRIPTION {NAME => 'f', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'ROW', REPLICATION_SCOPE => '0', VERSIONS => '1', COMPRESSION => 'NONE', MIN_VERSIONS => '0', TTL => 'FOREVER', KEEP_DELETED_CELLS => 'FALSE', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'true'} 1 row(s) in 0.2190 seconds hbase(main):021:0>scan 'test_table' ROW COLUMN+CELL row_01 column=f:col, timestamp=1478102698687, value=maizi row_01 column=f:name, timestamp=1478104345828, value=Andy row_02 column=f:name, timestamp=1478104477628, value=Andy2 row_03 column=f:name, timestamp=1478104823358, value=Andy3 3 row(s) in 0.2270 seconds hbase(main):022:0>scan 'test_table' ROW COLUMN+CELL row_01 column=f:col, timestamp=1478102698687, value=maizi row_01 column=f:name, timestamp=1478104345828, value=Andy row_02 column=f:name, timestamp=1478104477628, value=Andy2 row_03 column=f:name, timestamp=1478104823358, value=Andy3 3 row(s) in 0.1480 seconds hbase(main):023:0>scan 'test_table',{VERSIONS=>3} ROW COLUMN+CELL row_01 column=f:col, timestamp=1478102698687, value=maizi row_01 column=f:name, timestamp=1478104345828, value=Andy row_02 column=f:name, timestamp=1478104477628, value=Andy2 row_03 column=f:name, timestamp=1478104823358, value=Andy3 3 row(s) in 0.1670 seconds hbase(main):024:0> 1 package zhouls.bigdata.HbaseProject.Test1; 2 3 import javax.xml.transform.Result; 4 5 import org.apache.hadoop.conf.Configuration; 6 import org.apache.hadoop.hbase.HBaseConfiguration; 7 import org.apache.hadoop.hbase.TableName; 8 import org.apache.hadoop.hbase.client.Delete; 9 import org.apache.hadoop.hbase.client.Get; 10 import org.apache.hadoop.hbase.client.HTable; 11 import org.apache.hadoop.hbase.client.Put; 12 import org.apache.hadoop.hbase.util.Bytes; 13 14 public class HBaseTest { 15 public static void main(String[] args) throws Exception { 16 HTable table = new HTable(getConfig(),TableName.valueOf("test_table"));//表名是test_table 17 Put put = new Put(Bytes.toBytes("row_04"));//行键是row_04 18 put.add(Bytes.toBytes("f"),Bytes.toBytes("name"),Bytes.toBytes("Andy0"));//列簇是f,列修饰符是name,值是Andy0 19 // put.add(Bytes.toBytes("f2"),Bytes.toBytes("name"),Bytes.toBytes("Andy3"));//列簇是f2,列修饰符是name,值是Andy3 20 table.put(put); 21 table.close(); 22 23 // Get get = new Get(Bytes.toBytes("row_04")); 24 // get.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("age"));如现在这样,不指定,默认把所有的全拿出来 25 // org.apache.hadoop.hbase.client.Result rest = table.get(get); 26 // System.out.println(rest.toString()); 27 // table.close(); 28 29 // Delete delete = new Delete(Bytes.toBytes("row_2")); 30 // delete.deleteColumn(Bytes.toBytes("f1"), Bytes.toBytes("email")); 31 // delete.deleteColumn(Bytes.toBytes("f1"), Bytes.toBytes("name")); 32 // table.delete(delete); 33 // table.close(); 34 35 36 // Delete delete = new Delete(Bytes.toBytes("row_03")); 37 // delete.deleteColumn(Bytes.toBytes("f"), Bytes.toBytes("name")); 38 // delete.deleteColumns(Bytes.toBytes("f"), Bytes.toBytes("name")); 39 // table.delete(delete); 40 // table.close(); 41 } 42 43 public static Configuration getConfig(){ 44 Configuration configuration = new Configuration(); 45 // conf.set("hbase.rootdir","hdfs:HadoopMaster:9000/hbase"); 46 configuration.set("hbase.zookeeper.quorum", "HadoopMaster:2181,HadoopSlave1:2181,HadoopSlave2:2181"); 47 return configuration; 48 } 49 } hbase(main):038:0>scan 'test_table' ROW COLUMN+CELL row_01 column=f:col, timestamp=1478102698687, value=maizi row_01 column=f:name, timestamp=1478104345828, value=Andy row_02 column=f:name, timestamp=1478104477628, value=Andy2 row_03 column=f:name, timestamp=1478123664884, value=Andy3 3 row(s) in 0.1910 seconds hbase(main):039:0>scan 'test_table' ROW COLUMN+CELL row_01 column=f:col, timestamp=1478102698687, value=maizi row_01 column=f:name, timestamp=1478104345828, value=Andy row_02 column=f:name, timestamp=1478104477628, value=Andy2 row_03 column=f:name, timestamp=1478123664884, value=Andy3 row_04 column=f:name, timestamp=1478123917775, value=Andy0 4 row(s) in 0.1310 seconds delete.deleteColumn和delete.deleteColumns区别是: deleteColumn是删除某一个列簇里的最新时间戳版本。 delete.deleteColumns是删除某个列簇里的所有时间戳版本。 1 package zhouls.bigdata.HbaseProject.Test1; 2 3 import javax.xml.transform.Result; 4 5 import org.apache.hadoop.conf.Configuration; 6 import org.apache.hadoop.hbase.HBaseConfiguration; 7 import org.apache.hadoop.hbase.TableName; 8 import org.apache.hadoop.hbase.client.Delete; 9 import org.apache.hadoop.hbase.client.Get; 10 import org.apache.hadoop.hbase.client.HTable; 11 import org.apache.hadoop.hbase.client.Put; 12 import org.apache.hadoop.hbase.util.Bytes; 13 14 public class HBaseTest { 15 public static void main(String[] args) throws Exception { 16 HTable table = new HTable(getConfig(),TableName.valueOf("test_table"));//表名是test_table 17 Put put = new Put(Bytes.toBytes("row_04"));//行键是row_04 18 put.add(Bytes.toBytes("f"),Bytes.toBytes("name"),Bytes.toBytes("Andy1"));//列簇是f,列修饰符是name,值是Andy0 19 // put.add(Bytes.toBytes("f2"),Bytes.toBytes("name"),Bytes.toBytes("Andy3"));//列簇是f2,列修饰符是name,值是Andy3 20 table.put(put); 21 table.close(); 22 23 // Get get = new Get(Bytes.toBytes("row_04")); 24 // get.addColumn(Bytes.toBytes("f1"), Bytes.toBytes("age"));如现在这样,不指定,默认把所有的全拿出来 25 // org.apache.hadoop.hbase.client.Result rest = table.get(get); 26 // System.out.println(rest.toString()); 27 // table.close(); 28 29 // Delete delete = new Delete(Bytes.toBytes("row_2")); 30 // delete.deleteColumn(Bytes.toBytes("f1"), Bytes.toBytes("email")); 31 // delete.deleteColumn(Bytes.toBytes("f1"), Bytes.toBytes("name")); 32 // table.delete(delete); 33 // table.close(); 34 35 36 // Delete delete = new Delete(Bytes.toBytes("row_03")); 37 // delete.deleteColumn(Bytes.toBytes("f"), Bytes.toBytes("name")); 38 // delete.deleteColumns(Bytes.toBytes("f"), Bytes.toBytes("name")); 39 // table.delete(delete); 40 // table.close(); 41 } 42 43 public static Configuration getConfig(){ 44 Configuration configuration = new Configuration(); 45 // conf.set("hbase.rootdir","hdfs:HadoopMaster:9000/hbase"); 46 configuration.set("hbase.zookeeper.quorum", "HadoopMaster:2181,HadoopSlave1:2181,HadoopSlave2:2181"); 47 return configuration; 48 } 49 } delete.deleteColumn和delete.deleteColumns区别是: deleteColumn是删除某一个列簇里的最新时间戳版本。 delete.deleteColumns是删除某个列簇里的所有时间戳版本。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6156265.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

《Android App开发入门:使用Android Studio 2.X开发环境》——2-6 输入字段 EditText 组件

2-6 输入字段 EditText 组件 除了按钮外,另一种常见的基本输入组件是EditText。 getText():获取用户输入的文字 EditText 组件的用途是让用户输入文字,在程序中可用 getText()获取用户输入的内容。 getText() 方法返回的是 Android SDK中定义的 Editable 类型的对象,因此要当字符串处理,必须再调用 toString() 方法进行转换。 setText():设置 TextView 显示的文字 如果要设置 TextView 组件上显示的文字,那么可以调用 TextView 类的 setText() 方法。若txv为TextView 类的对象,则设置让 TextView 显示“您好!”。 范例2-2: 加入 EditText 组件 在这个范例中使用 EditText 组件,并用程序

优秀的个人博客,低调大师

不是你无法入门自然语言处理(NLP),而是你没找到正确的打开方式

〇、序 之前一段时间,在结合深度学习做 NLP 的时候一直有思考一些问题,其中有一个问题算是最核心一个:究竟深度网络是怎么做到让各种 NLP 任务解决地如何完美呢?到底我的数据在 NN 中发什么了什么呢? 并且,不少的 terms like: 词向量、word embedding、分布式表示、word2vec、glove 等等,这一锅粥的名词术语分别代表什么,他们具体的关系是什么,他们是否处于平级关系? 出于对知识结构追求完整梳理的强迫症的老毛病,于是不停地查资料、思考、keep revolving…… 然后就感觉有一点小进展了。想到,不如将个人对其的理解,无论对错,先拿出来跟peer分享下,或许能交换出更有意义的东西呢? 整篇文章的构架是按照属于概念在逻辑上的先后大小顺序,一层一层一级一级地往下剖析、比较、说明。 另外说明下,here整

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册